如何在Python中选择性导入模块?
我有几个不同的模块,我需要根据不同的情况来导入其中一个,比如:
if check_situation() == 1:
import helper_1 as helper
elif check_situation() == 2:
import helper_2 as helper
elif ...
...
else:
import helper_0 as helper
这些助手模块里包含了相同的字典,比如 dict01
、dict02
、dict03
……但是在不同的情况下,它们的值是不同的。
不过,这样做有一些问题:
- 导入语句都写在文件的顶部,但这里的
check_situation()
函数需要一些前提条件,所以它现在离顶部很远。 - 不止一个文件需要这个助手模块,所以用这种方式导入显得很麻烦,也不太好看。
那么,应该怎么重新安排这些助手模块呢?
4 个回答
5
你可以使用 __import__()
这个函数,它接受一个字符串并返回对应的模块:
helper=__import__("helper_{0}".format(check_situation()))
举个例子:
In [10]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': ")))
enter 'c' or '': c #imports cmath
In [11]: mod.__file__
Out[11]: '/usr/local/lib/python2.7/lib-dynload/cmath.so'
In [12]: mod=__import__("{0}math".format(raw_input("enter 'c' or '': ")))
enter 'c' or '':
In [13]: mod.__file__
Out[13]: '/usr/local/lib/python2.7/lib-dynload/math.so'
正如 @wim 提到的,以及在 Python 3.x 的文档中关于 __import__()
的说明:
这个函数用来导入一个模块。因为这个函数主要是给 Python 解释器使用的,不太适合普通开发者,所以更推荐使用
importlib.import_module()
来以编程的方式导入模块。
5
首先,导入语句并不一定要放在文件的最上面,这其实更多是个风格上的建议。
现在,importlib
和一个dict
可以用来替代你那一长串的if
/elif
判断:
import importlib
d = {1: 'helper_1', 2: 'helper_2'}
helper = importlib.import_module(d.get(check_situation(), 'helper_0'))
不过这其实只是语法上的一种简化,我觉得你可能还有更重要的事情要处理。听起来你需要重新考虑一下你的数据结构,并且重新设计一下代码。
每当你有像dict01
、dict02
、dict03
这样的变量名时,这就说明你需要提升一下自己的水平,应该有一个包含多个dict
的容器,比如一个列表。同样的,你的“辅助”模块名如果也带有数字,情况也是一样的。
1
我自己解决了这个问题,参考了@Michael Scott Cuthbert的内容。
# re_direct.py
import this_module
import that_module
wanted = None
# caller.py
import re-direct
'''
many prerequisites
'''
def imp_now(case):
import re_direct
if case1:
re_direct.wanted = re_direct.this_module
elif case2:
re_direct.wanted = re_direct.that_module
然后,如果在调用者那里,我调用了imp_now,那么无论是在调用者的文件中,还是在其他文件中调用这个wanted,都会被重定向到this_or_that_module。
另外,因为我只在一个函数里导入了re_direct,所以你在其他地方看不到这个模块,只能看到wanted。