2012-10-12 7 views
15

Ho scritto un piccolo wrapper per urllib (python3). È corretto e sicuro per importare il modulo in se?Python - importa in se

if self.response_encoding == 'gzip': 
    import gzip 

non ho trovato alcun PEP su questo codice. Tuttavia, mi dà fastidio.

+1

assicurati di non chiamare nessuna funzione proveniente da questo pacchetto se non viene importata – njzk2

+0

Sì, lo è. Perché ti dà fastidio? –

+0

Volevo chiedere e essere sicuro. Forse dovrei usare la parola 'preoccupata'. L'inglese non è la mia lingua madre. –

risposta

19

il Pyt la libreria standard di hon lo usa, quindi è sicuramente appropriato e sicuro. Vedere la os module source per un esempio eccellente:

if 'posix' in _names: 
    name = 'posix' 
    linesep = '\n' 
    from posix import * 
    try: 
     from posix import _exit 
    except ImportError: 
     pass 
    import posixpath as path 
    import posix 
    __all__.extend(_get_exports_list(posix)) 
    del posix 

E 'abbastanza comune condizionalmente moduli di importazione in pitone. Invece di if, vedrete spesso una combinazione try:/except ImportError: troppo:

try: 
    from subprocess import check_output 
except ImportError: 
    # Python 2.6 and before 
    def check_output(*popenargs, **kwargs): 
     from subprocess import Popen 
     if 'stdout' in kwargs: 
      raise ValueError('stdout argument not allowed, it will be ' 
          'overridden.') 
     process = Popen(stdout=PIPE, *popenargs, **kwargs) 
     output, unused_err = process.communicate() 
     retcode = process.poll() 
     if retcode: 
      cmd = kwargs.get("args") 
      if cmd is None: 
       cmd = popenargs[0] 
      raise CalledProcessError(retcode, cmd) 
     return output 

Qui, abbiamo praticamente utilizziamo l'equivalente morale di un test if: se è possibile importare check_output, si fa così, altrimenti definire la funzione completa Qui.

Una dichiarazione di importazione è solo una rilegatura di un pezzo di codice esterno a un nome locale. L'utilizzo di un flusso di controllo if per il controllo dell'importazione non è diverso dall'assegnazione di una variabile in un'istruzione if a tale riguardo. È necessario assicurarsi di non finire usando il nome senza che sia definito in alcun modo.

+0

+1 - 'try/except ImportError' è stato il mio primo istinto a rispondere a questa domanda. – mgilson

3

Certo, va bene. Può persino essere necessario nei casi in cui il modulo abbia un codice di inizializzazione che non si desidera eseguire sempre.

8

Questo è un idioma ragionevolmente comune in realtà. Avrete a volte vedere per scegliere tra i diversi moduli:

if system == 'linux': 
    import linuxdeps as deps 
elif system == 'win32': 
    import win32deps as deps 

Quindi, supponendo che sia linuxdeps e win32deps hanno le stesse funzioni, si può semplicemente utilizzare:

deps.func() 

Questo è usato anche per ottenere os.path nella libreria standard (parte del codice sorgente per os segue):

if 'posix' in _names: 
    name = 'posix' 
    linesep = '\n' 
    from posix import * 
    try: 
     from posix import _exit 
    except ImportError: 
     pass 
    import posixpath as path 

    import posix 
    __all__.extend(_get_exports_list(posix)) 
    del posix 

elif 'nt' in _names: 
    name = 'nt' 
    linesep = '\r\n' 
    from nt import * 
    try: 
     from nt import _exit 
    except ImportError: 
     pass 
    import ntpath as path 

    import nt 
    __all__.extend(_get_exports_list(nt)) 
    del nt 
1

È sicuro? Sì. Come Martijin's answer ha sottolineato che Python ufficiale usa questo.

È corretto? Dipende. Python performance docs fa notare che anche se python può evitare di importare lo stesso modulo, c'è ancora un sovraccarico.

Quindi credo che dovresti chiedertelo, quanto spesso l'affermazione è vera. Se molto spesso, ci sarà un sovraccarico, e dovresti importarlo all'inizio del file. Se non spesso, importa se l'istruzione è una scelta saggia.