Я написал небольшую обертку для urllib (python3). Является правильным и безопасным для импорта модуля, если?
if self.response_encoding == 'gzip':
import gzip
Я не нашел PEP об этом коде. Однако это беспокоит меня.
Я написал небольшую обертку для urllib (python3). Является правильным и безопасным для импорта модуля, если?
if self.response_encoding == 'gzip':
import gzip
Я не нашел PEP об этом коде. Однако это беспокоит меня.
Стандартная библиотека 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
Конечно, это хорошо. Это может быть даже необходимо в тех случаях, когда модуль имеет код инициализации, который вы не всегда хотите запускать.
Это безопасно? Да. Как ответ Martijin указал, что официальный Python использует это.
Это правильно? Зависит. Python docs указывает, что даже несмотря на то, что python может избежать импорта одного и того же модуля, все еще накладные расходы.
Итак, я считаю, вы должны спросить себя, как часто утверждение if истинно. Если очень часто, тогда будут большие накладные расходы, и вы должны импортировать их в начале файла. Если не часто, то импорт в выражении if является разумным выбором.