2010-08-31 55 views
12

假設def my_function():位於my_apps.views我想動態地導入「my_function」而不使用exec或eval之類的東西。如何動態導入python模塊函數?

有沒有辦法做到這一點。我希望做類似的東西:

創建my_function = import_func( 「my_apps.views.my_function」)

創建my_function() ...代碼被執行

回答

17

你想

my_function = getattr(__import__('my_apps.views'), 'my_function') 

如果你碰巧知道在編譯時的函數的名稱,就可以縮短這

my_function = __import__('my_apps.views').my_function 

這將加載my_apps.views,然後將其my_function屬性分配給本地my_function

如果你確定你只想要一個函數,那麼這是可以接受的。如果你想要一個以上的屬性,你可以這樣做:

views = __import__('my_apps.views') 
my_function = getattr(views, 'my_function') 
my_other_function = getattr(views, 'my_other_function') 
my_attribute = getattr(views, 'my_attribute') 

,因爲它是更具可讀性和保存你__import__幾個電話。再次,如果你知道名字,代碼可以縮短如上。

您也可以使用imp模塊中的工具來做到這一點,但它更復雜。

+2

會有上面的語句__import__問題(AttributeError的)。除非指定了導入列表,否則導入將返回第一個模塊(my_apps)。你需要這樣的: 'my_function = __import __('my_apps.views',globals(),locals(),['my_function'])。my_function' 請參閱[python doc about __import__](https://docs.python .ORG/2 /庫/功能。html #__ import__) – marco 2016-03-10 00:53:25

+0

marco發佈的解決方案適用於我!謝謝 – giopromolla 2016-08-05 17:36:01

+0

對我來說,這個嘗試從'my_apps'而不是'my_apps.views'導入函數。 – oarfish 2017-11-17 10:18:43

5

請注意,Python 2.7添加了importlib module, 便利包裝__import__()和3.1功能的backport。

該模塊是Python 3.1中提供的完整功能的同名軟件包中的一小部分,它提供了完整的導入實現。這裏提供了什麼來幫助緩解從2.7到3.1的過渡。

importlib.import_module(name, package=None)

導入模塊。 name參數指定以絕對或相對方式導入的模塊(例如,pkg.mod或..mod)。如果名稱是以相對術語指定的,那麼必須將package參數指定給作爲解析包名稱的錨點的包(例如,import_module('.. mod','pkg.subpkg')將導入pkg的.mod)。指定的模塊將被插入到sys.modules並返回。

+0

Python 2.7中可用的importlib的子集也可在PyPI上使用,並且在那裏用於Python 2.3及更高版本。 – 2010-09-20 22:33:34

1

我剛纔寫的代碼,似乎什麼很多人需要,所以即使後來我表現出來

def my_import(module_name,func_names = [],cache = False): 
    if module_name in globals() and cache: 
     return True 
    try: 
     m = __import__(module_name, globals(), locals(), func_names, -1) 
     if func_names: 
      for func_name in func_names: 
       globals()[func_name] = getattr(m,func_name) 
     else: 
      globals()[module_name] = m 
     return True 
    except ImportError: 
     return False 
def my_imports(modules): 
    for module in modules: 
     if type(module) is tuple: 
      name = module[0] 
      funcs = module[1] 
     else: 
      name = module 
      funcs = [] 
     if not my_import(name, funcs): 
      return module 
    return '' 

def checkPluginsImports(plugin,modules): 
    c = my_imports(modules) 
    if c: 
     print plugin +" has errors!: module '"+c+"' not found" 

# example: file test.py with "x" function 
def d(): 
    checkPluginsImports('demoPlugin',[('test',['x'])]) 

d() 
x() 
0
def import_by_string(full_name): 
    module_name, unit_name = full_name.rsplit('.', 1) 
    return getattr(__import__(module_name, fromlist=['']), unit_name) 


exists = import_by_string("os.path.exists") 
+0

從版本2.4開始(從2004年開始),Python已經具有'rsplit()'函數,所以執行'module_name,unit_name = full_name.rsplit('。',1)'比您正在做的更有效率。 – Anthon 2017-03-04 08:35:34

+0

謝謝。沒想過。 – Archibald 2017-03-04 18:12:59