このテストのファイルは次のとおりです。
main.py
app/
|- __init__.py
|- master.py
|- plugin/
|- |- __init__.py
|- |- p1.py
|- |_ p2.py
アイデアは、プラグイン対応のアプリを用意することです。新しい .py または .pyc ファイルは、API に準拠するプラグインにドロップできます。
master.py
アプリ自体だけでなく、すべてのプラグインがアクセスする必要があるグローバル変数と関数を含むアプリ レベルのファイルがあります。このテストでは、「アプリ」は app/__init__.py のテスト関数で構成されます。実際には、アプリは別のコード ファイルに移動される可能性がありますがimport master
、そのコード ファイルで を使用して への参照を取り込みますmaster
。
ファイルの内容は次のとおりです。
main.py:
import app
app.test()
app.test2()
app/__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__
の使用とは異なることをしていることは明らかです。import
Python のドキュメントでは、 import を使用すると__import__
内部的にステートメントに変換されるだけであると述べられていますが、目に見える以上のことが行われている必要があります。
アプリはプラグイン ベースであるため、メイン アプリで明示的なインポート ステートメントをコーディングすることは、もちろん実現不可能です。内でインポート自体を使用する
ここで何が欠けていますか?を使用してモジュールを手動でインポートするときに、Python を期待どおりに動作させるにはどうすればよい__import__
ですか? 相対インポートの考え方を完全に理解していないか、インポートが発生している場所 (つまり、コード ファイルのルートではなく関数内) に関して何かが欠けているようです。
編集:次の可能性のある解決策が見つかりましたが、失敗しました:
m = __import__("p2",globals(),locals(),"plugin")
(上記とまったく同じエラーを返します)
m = __import__("plugin",fromlist="p2")
(app.plugin.p2 ではなく、app.plugin への参照を返します)
m = __import__("plugin.p2",globals(),locals())
(app.plugin.p2 ではなく、app.plugin への参照を返します)
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