2010-08-31 15 views
12

Kusur varsa my_function(): my_apps.views'ta yer alır. "My_function" öğesini dinamik olarak exec veya eval gibi bir şey kullanmadan aktarmak istiyorum. Bunu gerçekleştirmek için yine de var mıdır? Ben benzer bir şey yapmak arıyorum:Bir python modül işlevini dinamik olarak nasıl alabilirim?

işlevim = import_func ("my_apps.views.my_function")

işlevim() ... kodu

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

cevap

17

yürütülür derleme zamanında fonksiyonun adını bilmek edersek

, sen

my_function = __import__('my_apps.views').my_function 
bu kısaltabilir

Bu, my_apps.views yüklenir ve daha sonra yerel my_function için my_function özniteliğini atar.

Yalnızca tek işlevini istediğinizden eminseniz, bu kabul edilebilirdir. Birden fazla özellik istiyorsanız, yapabilirsiniz:

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') 

daha okunabilir ve size __import__ bazı aramaları kaydeder olarak. Yine, isimleri biliyorsanız, kod yukarıdaki gibi kısaltılabilir.

Bunu, imp modülünden araçlarla da yapabilirsiniz, ancak daha karmaşıktır.

+2

yukarıdaki __import__ ifadelere problemleri (AttributeError) olacak göstermektedir. İçe aktarma listesi belirtilmedikçe, ilk modülü (my_apps) içe aktarır. Şunun gibi bir şeye ihtiyacınız vardır: 'my_function = __import __ ('my_apps.views', globals(), yerlileri(), ['my_function']). My_function' Bkz. [Python doc about __import__] (https: //docs.python .org/2/kütüphane/işlev görür.html #__ import__) – marco

+0

marco tarafından gönderilen çözüm benim için çalışıyor! Teşekkürler – giopromolla

+0

Bu benim için 'my_apps.views' yerine' my_apps' işlevini içe aktarma girişiminde bulunuyor. – oarfish

5

Python 2.7'un importlib module, kolaylıklı paketleyicileri için __import__() ve 3.1 özellikli bir arkaport eklediğini unutmayın.

Bu modül, Python 3.1'den aynı adın tam özellikli paketinde, içe aktarmanın tam olarak uygulanmasını sağlayan küçük bir alt kümesidir. Burada 2.7'den 3.1'e geçişte kolaylık sağlamak için neler sağlanmıştır.

importlib.import_module(name, package=None)

İçe bir modül. Ad argümanı, mutlak veya göreceli olarak hangi modülün içe aktarılacağını belirtir (ör. Pkg.mod veya ..mod). Eğer isim göreceli olarak belirtilirse, paketin argümanı, paket ismini çözmek için ankraj olarak davranacak olan pakete belirtilmelidir (örn. Import_module ('.. mod', 'pkg.subpkg') pkg mod). Belirtilen modül sys.modules içine eklenir ve iade edilir.

+0

Python 2.7'de bulunan importlib'in alt kümesi de PyPI'da bulunabilir ve Python 2.3 ve üzeri ile çalışmak için oraya geri gönderilir. –

1

Sadece bu kodu yazmış ve bir sürü insan ne gerek görünüyor, bu yüzden bile sonradan ben

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 sürümünden (2004'ten itibaren), Python işlevi rsplit() 'işlevine sahipti, yaptığınız şeyden daha çok 'modül_name, unit_name = full_name.rsplit ('. ', 1)' yapmak çok daha verimlidir. – Anthon

+0

Teşekkürler. Düşünmedim. – Archibald

İlgili konular