2012-10-12 48 views
15

我爲urllib(python3)編寫了一個小封裝。是否正確安全要導入模塊如果Python - 導入if if

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

我沒有找到關於此代碼的任何PEP。但是,它困擾我。

+1

只要不導入任何來自該軟件包的函數,就不要調用它 – njzk2

+0

是的。它爲什麼打擾你? –

+0

我想問,並確定。也許我應該用'擔心'這個詞。英語不是我的母語。 –

回答

19

的PYT洪標準庫使用它,所以它是絕對正確和安全的。一個很好的例子見os module source

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,這樣做,否則定義全功能這裏。

導入語句只是將外部代碼段重新綁定到本地名稱。在這方面,使用if控制流來控制導入與在if語句中分配變量沒有什麼不同。您需要確保您不會以任何方式定義名稱。

+0

+1 - '嘗試/除了ImportError'是我第一次直接回答這個問題。 – mgilson

3

好的,沒關係。在模塊有初始化代碼的情況下,甚至有必要運行它。

8

這實際上是一個相當常見的習慣用法。有時你會看到它的不同模塊之間的挑選:

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

然後,假設兩個linuxdepswin32deps具有相同的功能,你可以使用它:

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 
1

安全嗎?是。正如Martijin's answer指出,官方的Python使用這個。

這是正確的嗎?依靠。 Python performance docs指出,儘管python可以避免導入相同的模塊,但仍然存在開銷。

所以我相信你應該問自己,if語句是多少次是正確的。如果經常發生,那麼會有很大的開銷,並且應該在文件的開始處導入它。如果不經常,那麼輸入if語句是明智的選擇。