我想使用imp.load_source
动态加载源代码中的python(2.7而非3.x)模块,如果我没有将源代码路径附加到sys.path
,则本地导入无法正常工作。在这种情况下,如何通过本地导入解决冲突模块名称?
我已经搜索了一段时间,无法找到解决方案。有任何想法吗?谢谢!
我喜欢的文件结构:
/tmp
|---runner
| |-runner.py
/tmp/modules
|---bundle1
| |--bundle
| | |-__init__.py
| | |-index.py
| |-main.py
|
|---bundle2
|--bundle
| |-__init__.py
| |-index.py
|-main.py
在 runner.py
中import os
import imp
import sys
sys.path.append("/tmp/modules/bundle1")
module_a = imp.load_source("Bundle1", "/tmp/modules/bundle1/main.py")
sys.path.append("/tmp/modules/bundle2")
module_b = imp.load_source("Bundle2", "/tmp/modules/bundle2/main.py")
module_a.start()
module_b.start()
在 bundle1 / main.py
中from bundle import index
def start():
index.a_func()
if __name__ == "__main__":
start()
在 bundle2 / main.py
中from bundle import index
def start():
index.b_func()
if __name__ == "__main__":
start()
因为from bundle
b_func()
,bundle2/main.py
的冲突
答案 0 :(得分:0)
这里发生的事情是进口混乱。 Python正在缓存这样一个事实:它知道一个名为bundle
的模块以及一个名为bundle.index
的模块。 This post should help you understand imports a little more.如果你在你的负载之间打印sys.modules['bundle']
,那就不那么神秘了。
print sys.modules.get('bundle', None)
# => yields None
sys.path.append("/tmp/modules/bundle1")
module_a = imp.load_source("Bundle1", "/tmp/modules/bundle1/main.py")
print sys.modules.get('bundle', None)
# => <module 'bundle' from '/tmp/modules/bundle1/bundle/__init__.pyc>
sys.path.append("/tmp/modules/bundle2")
module_b = imp.load_source("Bundle2", "/tmp/modules/bundle2/main.py")
print sys.modules.get('bundle', None)
# => <module 'bundle' from '/tmp/modules/bundle1/bundle/__init__.pyc>
如果您确实需要在一个命名空间中两次加载完全相同的模块名称,则需要在sys.modules
之间删除其中的条目。此外,由于您只是追加到您的路径,因此当您加载module_b
时,python会在找到/tmp/modules/bundle1/bundle/
之前找到/tmp/modules/bundle2/bundle
所以,要彻底解决您的问题。问题,您必须先添加信息或将其从sys.path
中删除。但一般来说,这实际上并不是很好的做法,当然如果您对模块名称有任何控制权,你应该改变它们。
print sys.modules.get('bundle', None)
# => yields None
sys.path.append("/tmp/modules/bundle1")
module_a = imp.load_source("Bundle1", "/tmp/modules/bundle1/main.py")
print sys.modules.get('bundle', None)
# => <module 'bundle' from '/tmp/modules/bundle1/bundle/__init__.pyc>
module_a.start()
# Delete python's knowledge of bundle1
del sys.modules['bundle']
del sys.modules['bundle.index']
sys.path.pop(sys.path.index('/tmp/modules/bundle1')
sys.path.append("/tmp/modules/bundle2")
module_b = imp.load_source("Bundle2", "/tmp/modules/bundle2/main.py")
print sys.modules.get('bundle', None)
# => <module 'bundle' from '/tmp/modules/bundle2/bundle/__init__.pyc>
module_b.start()
请注意,由于您删除了python对bundle1的了解,因此在moudle_a.start()
之后尝试del
会导致AttributeError
希望这有帮助。