以下是此测试中的文件:
main.py
app/
|- __init__.py
|- master.py
|- plugin/
|- |- __init__.py
|- |- p1.py
|- |_ p2.py
我们的想法是拥有一个支持插件的应用程序。可以将新的 .py 或 .pyc 文件放入符合我的 API 的插件中。
我master.py
在应用程序级别有一个文件,其中包含任何和所有插件可能需要访问的全局变量和函数,以及应用程序本身。就本测试而言,“app”由 app/__init__.py 中的一个测试函数组成。在实践中,应用程序可能会被移动到单独的代码文件中,但是我只是import master
在该代码文件中使用来引入对master
.
这是文件内容:
主要.py:
import app
app.test()
app.test2()
应用程序/__init__.py:
import sys, os
from plugin import p1
def test():
print "__init__ in app is executing test"
p1.test()
def test2():
print "__init__ in app is executing test2"
scriptDir = os.path.join ( os.path.dirname(os.path.abspath(__file__)), "plugin" )
print "The scriptdir is %s" % scriptDir
sys.path.insert(0,scriptDir)
m = __import__("p2", globals(), locals(), [], -1)
m.test()
应用程序/master.py:
myVar = 0
应用程序/插件/__init__.py:
<empty file>
应用程序/插件/p1.py:
from .. import master
def test():
print "test in p1 is running"
print "from p1: myVar = %d" % master.myVar
应用程序/插件/p2.py:
from .. import master
def test():
master.myVar = 2
print "test in p2 is running"
print "from p2, myVar: %d" % master.myVar
由于我明确导入了p1
模块,所以一切都按预期工作。但是,当我使用__import__
导入 p2 时,出现以下错误:
__init__ in app is executing test
test in p1 is running
from p1: myVar = 0
__init__ in app is executing test2
The scriptdir is ....../python/test1/app/plugin
Traceback (most recent call last):
File "main.py", line 4, in <module>
app.test2()
File "....../python/test1/app/__init__.py", line 17, in test2
m = __import__("p2", globals(), locals(), [], -1)
File "....../python/test1/app/plugin/p2.py", line 1, in <module>
from .. import master
ValueError: Attempted relative import in non-package
执行一直通过 test() 函数并在 test2() 尝试执行其__import__
语句时立即出错,而 p2 又尝试执行相对导入(当 p1 通过 import 语句显式导入时确实有效,回想一下)
很明显, using__import__
所做的事情与 usingimport
语句不同。Python 文档指出,使用 import 只是在__import__
内部转换为语句,但必须进行更多的操作而不是看起来。
由于该应用程序是基于插件的,因此在主应用程序中编写显式导入语句当然是不可行的。在
我在这里想念什么?使用手动导入模块时,如何让 Python 表现得如预期__import__
?似乎我可能没有完全理解相对导入的想法,或者我只是缺少关于导入发生位置的一些东西(即在函数内部而不是在代码文件的根目录)
编辑:我发现了以下可能但不成功的解决方案:
m = __import__("p2",globals(),locals(),"plugin")
(返回与上面相同的错误)
m = __import__("plugin",fromlist="p2")
(返回对 app.plugin 的引用,而不是对 app.plugin.p2 的引用)
m = __import__("plugin.p2",globals(),locals())
(返回对 app.plugin 的引用,而不是对 app.plugin.p2 的引用)
import importlib
m = importlib.import_module("plugin.p2")
(返回:)
Traceback (most recent call last):
File "main.py", line 4, in <module>
app.test2()
File "....../python/test1/app/__init__.py", line 20, in test2
m = importlib.import_module("plugin.p2")
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
ImportError: No module named plugin.p2