Python-импорт в if

Я написал небольшую обертку для urllib (python3). Это правильный и безопасное импортировать модуль в if?

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

Я не нашел никакого PEP об этом коде. Однако меня это беспокоит.

4 ответов


стандартная библиотека Python использует его, поэтому он наиболее определенно правильный и безопасный. Вижу os модуль отличный пример:

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

это довольно распространено для условного импорта модулей в python. Вместо if, вы часто будете видеть try:/except ImportError: сочетание тоже:

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

здесь мы в основном используем моральный эквивалент if ТЕСТ: Если вы можете импортировать check_output, сделайте так, в противном случае определите полная функция здесь.

оператор import-это просто повторная привязка внешнего фрагмента кода к локальному имени. С помощью if поток управления для управления импортом ничем не отличается от назначения переменной в if заявление в этой связи. Вам нужно убедиться, что вы не используете имя без его определения в любом случае.


это довольно распространенная идиома на самом деле. Иногда вы увидите его, чтобы выбрать между различными модулями:

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

затем, предполагая, что оба linuxdeps и win32deps имеют такие же функции, вы можете просто использовать это:

deps.func()

это даже используется, чтобы сделать os.path в стандартной библиотеке (часть исходного кода для os ниже):

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

Конечно, все в порядке. Это может быть даже необходимо в тех случаях, когда модуль имеет код инициализации, который вы не всегда хотите запускать.


Это безопасно? Да. As Martijin это указал, что официальный Python использует это.

разве это правильно? Зависит. Python performance docs указывает, что, хотя python может избежать импорта того же модуля, все еще есть накладные расходы.

поэтому я считаю, что вы должны спросить себя, как часто если утверждение верно. Если очень часто, то будут большие накладные расходы, и вы должны импортировать его в начале файла. Если не часто, то импорт в if оператор является мудрым выбором.