Skip to main content
 首页 » 编程设计

python之进行动态导入,这在 Python 中仍然是显式的

2025年05月04日9qq号

好吧,这有点复杂。

假设我在包中有一个模块:

a_package 
 |-- __init__.py 
 |-- a_module.py 

在 a_module.py 中,我声明了 A_Class:

# file location: a_package/a_module.py 
class A_Class(): 
    def say(self): 
        print ("cheese") 

我可以创建一个 A_Class 实例并调用 say 方法:

from a_package.a_module import A_Class 
my_object = A_Class() 
my_object.say() # this will display 'cheese' as expected 

但是,我想做一个更动态的方式(我打算有很多包和类,并且想让代码更容易写)。所以,我创建了一个名为 load_class

的函数
def load_class(package_name, module_name, class_name) 
    result = None 
    try: 
        exec('from ' + package_name + '.' + module_name + ' import ' + class_name) 
        exec('result = '+class_name) 
    except: 
        raise ImportError('Unable to load the class') 
    return result 
 
# Now, I can conveniently do this: 
A_Class = load_class('a_package', 'a_module', 'A_Class') 
my_object = A_Class() 
my_object.say() 
 
# or even shorter: 
load_class('a_package', 'a_module', 'A_Class')().say() 

程序按预期工作,但 IDE(我使用 pydev)不理解我的代码,无法执行智能感知(自动完成代码)。

如果我使用第一种方法,智能感知显然是有效的:

from a_package.a_module import A_Class 
my_object = A_Class() 
my_object. # when I press ".", there will be a popup to let me choose "say" method 

但如果我使用第二种方法,智能感知无法为我完成:

load_class('a_package', 'a_module', 'A_Class')(). # when I press ".", nothing happened 

我知道,这是在 Python 中进行动态导入的权衡。但是,我想知道是否有一些替代方法让我做第二种方法(可能不使用 exec)仍然可以让通用 IDE(例如 Pydev)的智能感知猜测里面的方法类?

编辑:为什么我需要这样做? 假设我有这样一个目录结构

fruit 
 |-- strawberry.py 
 |-- orange.py 
 
chocolate 
 |-- cadbury.py 
 |-- kitkat.py 
 
need_dynamic.py 

在 need_dynamic.py 中,我有这个脚本:

food_list = ['fruit', 'chocolate'] 
subfood_list = [['strawberry', 'orange'],['cadbury', 'kitkat']]  
# show food list and ask user to choose food 
for i in xrange(len(food_list)): 
    print i + " : " + food_list[i] 
food_index = int(raw_input('chose one')) 
# show subfood list and ask user to choose subfood  
for i in xrange(len(subfood_list[food_index])): 
    print i + " : " + subfood_list[food_index][i] 
subfood_index = int(raw_input('chose one')) 
# init the class 
my_class = load_class(food_list[food_index], subfood_list[food_index, subfood_index]) 
# the rest of the code 

这只是为了简化,实际上,我打算通过获取目录自动填充food_list和subfood_list。

假设您有一个数据分类框架,并且想让用户选择他们想要使用的方法。用户还应该能够通过简单地添加 python 包和模块来扩展框架。

我希望这个例子是合理的。

再次编辑 接受的答案没有解决智能感知问题。但它展示了如何更好地编码。我认为这是IDE问题而不是python问题。我会发布另一个问题。

请您参考如下方法:

你想要使用 __import__ 内置函数:

def load_class(package, mod_name, cls_name): 
    mod = __import__('.'.join((package, mod_name))) 
    return getattr(mod, cls_name) 

当然,如果您愿意,您可以将错误处理放回原处,老实说,我不太确定为什么您首先要这样做。对于大多数 事情,动态导入对我来说似乎是一种“代码味道”。请在开始使用之前评估您是否真的需要它。