2014-01-19 26 views
3

我想在Python中動態地導入配置文件。當我使用__import__和導入之間的Python區別爲

我的代碼工作正常:

import conf.config as config 

但是當我使用不能正常工作:

config = __import__("conf.config") 

下面是示例程序,結果運行它們時,我得到:

#regularimport.py 
import conf.config as config 

def read_values(cfg): 
    for varname in cfg.__dict__.keys(): 
     if varname.startswith('__'): 
      continue 
     value = getattr(cfg, varname) 
     yield (varname, value) 

for name,value in read_values(config): 
    print "Current config: %s = %s" % (name, value) 

結果:

$python regularimport.py 

Current config: SETTING_TWO = another setting 
Current config: SETTING_ONE = some setting 

動態導入:

#dynamicimport.py 
conf_str = "conf.config" 
config = __import__(conf_str) 

def read_values(cfg): 
    for varname in cfg.__dict__.keys(): 
     if varname.startswith('__'): 
      continue 
     value = getattr(cfg, varname) 
     yield (varname, value) 

for name,value in read_values(config): 
    print "Current config: %s = %s" % (name, value) 

結果:

$ python dynamicimport.py 
Current config: config = <module 'conf.config' from '/home/ubuntu/importex/conf/config.pyc'> 

我的問題是,爲什麼不同?更重要的是,如何使動態導入示例像常規導入一樣工作?

+0

第一個問題是,你爲什麼要使用['__import__'(http://docs.python.org/2/library/functions.html#__import__)。你讀過文檔嗎?他們不僅解釋它,而且告訴你如果你不想學習所有可能使用的可怕細節['importlib.import_module'](http://docs.python.org/2改爲/library/importlib.html#importlib.import_module)。 – abarnert

回答

6

作爲the documentation說明:

名稱變量的形式package.module的,通常,返回頂層包(名字向上直到第一點),命名的模塊名稱

所以,當你這樣做:

config = __import__("conf.config") 

這是不一樣的:

import conf.config as config 

反倒是更多的東西一樣:

import conf.config 
config = conf 

爲什麼?

因爲conf,而不是conf.config,是被import語句綁定的東西。 (當然,在import foo as bar中,顯然bar被綁定...但__import__並不意味着等效於import foo as bar,而是import foo。)文檔將進一步解釋。但結果是,你可能不應該首先使用__import__


在函數文檔,它說的最頂端:

注:這是沒有必要在日常Python編程,不像importlib.import_module()先進的功能。

,並在底部,與包解釋如何__import__作品後,爲什麼它的工作原理是這樣,它說:

如果你只是想通過名字導入模塊(可能在包裝內) ,請使用importlib.import_module()

所以,你可能會猜到,簡單的解決方案是使用importlib.import_module


如果你有使用Python 2.6,其中importlib不存在...好,那裏只是沒有簡單的解決方案。你可以自己創建import_module之類的東西,出imp。或者使用__import__,然後通過sys.modules挖掘。或者每個作品__import__然後通過getattr您的方式通過結果。或者以各種其他的黑客方式。是的,這很糟糕 - 這就是3.0和2.7固定它的原因。

2.6文檔給出了第二個黑客的例子。它適應您的情況:

__import__("conf.config") 
config = sys.modules["conf.config"] 
0

config = __import__("conf.config")不等於import conf.config as config

例如:

>>> import os.path as path 
>>> path 
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'> 

>>> __import__('os.path') 
<module 'os' from '/usr/lib/python2.7/os.pyc'> 

代替__import__使用importlib.import_module獲得分包/子模塊。

>>> import importlib 
>>> importlib.import_module('os.path') 
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'> 
+1

關於你的第一個例子:你如何設法在* nix和windows上同時運行一個控制檯? (/ usr vs C :) – Hyperboreus

+0

@Hyperboreus,我混合虛擬機輸出,真機意外。謝謝你的觀點。 – falsetru

相關問題