Here are the files in this test:
main.py app/ |- __init__.py |- master.py |- plugin/ |- |- __init__.py |- |- p1.py |- |_ p2.py
The idea is to have an application that supports the plugin. New .py or .pyc files can be dropped into plugins that match my API.
I have an master.py -level master.py file that contains global variables and functions that any plugin can access, as well as the application itself. For the purposes of this test, an “application” consists of a test function in app / __ init__.py. In practice, the application is likely to be moved to a separate code file, but then I would simply use import master in this code file to provide a link to master .
Here is the contents of the file:
main.py:
import app app.test() app.test2()
Appendix / __ __ INIT ru :.
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()
Application / master.py:
myVar = 0
application / plugin / __ __ INIT ru :.
<empty file>
application / plugin / p1.py:
from .. import master def test(): print "test in p1 is running" print "from p1: myVar = %d" % master.myVar
application / plugin / p2.py:
from .. import master def test(): master.myVar = 2 print "test in p2 is running" print "from p2, myVar: %d" % master.myVar
Since I explicitly import the p1 module, everything works as expected. However, when I use __import__ to import p2, I get the following error:
__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
Execution is performed completely through the test () function and errors exit correctly, since test2 () tries to execute the __import__ statement, which, in turn, tries to do relative imports (which does work when p1 is imported explicitly through the import statement, recall)
Clearly, using __import__ does something different than using the import statement. Python docs point out that using import simply translates to the __import__ statement inside, but should be more than it seems at first glance.
Since the application is plugin-based, encoding explicit import statements in the main application is, of course, impractical. Using the import itself inside
What am I missing here? How can I make Python behave as expected when manually importing modules using __import__ ? Perhaps I do not quite understand the idea of ​​relative imports, or that I just missed something regarding where the import occurs (i.e. inside a function, not in the root code file).
EDIT: I found the following possible but unsuccessful solutions:
m = __import__("p2",globals(),locals(),"plugin")
(returns the same exact error as above)
m = __import__("plugin",fromlist="p2")
(returns a link to app.plugin, not app.plugin.p2)
m = __import__("plugin.p2",globals(),locals())
(returns a link to app.plugin, not app.plugin.p2)
import importlib m = importlib.import_module("plugin.p2")
(returns :)
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