2012-10-12 50 views
15

Escribí poco envoltorio para urllib (python3). ¿Es propiamente dicha y seguro para importar el módulo en?Python - importar en if

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

No encontré ningún PEP sobre este código. Sin embargo, me molesta.

+1

simplemente asegúrese de no llamar a ninguna función que provenga de este paquete si no se importa – njzk2

+0

Sí lo es. Porque te molesta? –

+0

Quería preguntar y estar seguro. Tal vez debería usar palabras 'preocupadas'. El inglés no es mi lengua materna –

Respuesta

19

el Pyt La biblioteca estándar hon lo usa, por lo que definitivamente es apropiado y seguro. Ver el os module source para un excelente ejemplo:

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 

Es bastante común a los módulos de importación en forma condicional pitón. En lugar de if, a menudo se ve una combinación try:/except ImportError: también:

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 

Aquí, utilizamos básicamente el equivalente moral de una prueba de if: Si usted puede importar check_output, de hacerlo, de lo contrario definir la función completa aquí.

Una instrucción de importación es solo un enlace de una pieza externa de código a un nombre local. El uso de un flujo de control if para controlar la importación no es diferente de la asignación de una variable en una declaración if al respecto. Debes asegurarte de que no termines usando el nombre sin que esté definido de ninguna manera.

+0

+1 - 'try/except ImportError' fue mi primer instinto para responder esta pregunta también. – mgilson

3

Claro, está bien. Incluso puede ser necesario en los casos en que el módulo tiene un código de inicialización que no siempre desea ejecutar.

8

Esto es un modismo bastante común en realidad. A veces, verá que escoger entre diferentes módulos:

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

Entonces, asumiendo tanto linuxdeps y win32deps tienen las mismas funciones, sólo puede usarlo:

deps.func() 

Esto es incluso utilizado para obtener os.path en la biblioteca estándar (una parte del código fuente para os sigue):

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

¿Es seguro? Sí. Como Martijin's answer señaló que el oficial Python usa esto.

¿Es correcto? Depende Python performance docs señala que aunque python puede evitar importar el mismo módulo, todavía hay gastos generales.

Así que creo que debería preguntarse, con qué frecuencia la afirmación if es verdadera. Si ocurre con mucha frecuencia, habrá una gran sobrecarga y deberá importarla al principio del archivo. Si no es así a menudo, importar en una declaración if es una buena elección.