36

urllib (python3) の小さなラッパーを書きました。モジュールを ifにインポートするのは適切安全ですか?

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

このコードに関する PEP は見つかりませんでした。しかし、それは私を悩ませます。

4

4 に答える 4

38

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ステートメントで変数を割り当てることと同じです。どちらの方法でも定義せずに名前を使用してしまうことがないようにする必要があります。

于 2012-10-12T14:17:58.083 に答える
16

これは実際にはかなり一般的なイディオムです。異なるモジュールを選択するために時々表示されます。

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
于 2012-10-12T14:14:55.060 に答える
5

もちろん、それで結構です。モジュールに、常に実行したくない初期化コードがある場合でも必要になることがあります。

于 2012-10-12T14:09:25.190 に答える
3

安全ですか?はい。Martijin 's answerが指摘したように、公式の Python はこれを使用しています。

それは適切ですか?依存します。Python パフォーマンス ドキュメントでは、Python は同じモジュールのインポートを回避できますが、それでもオーバーヘッドがあると指摘しています。

したがって、if ステートメントが真である頻度を自問する必要があると思います。非常に頻繁な場合、大きなオーバーヘッドが発生するため、ファイルの先頭にインポートする必要があります。頻繁でない場合は、if ステートメントにインポートするのが賢明な選択です。

于 2016-11-24T20:06:21.347 に答える