我有一个Python应用程序,可在运行时将插件作为模块加载。
module = importlib.import_module("plugins." + modulename)
现在,我想使用pyinstaller构建可执行文件,但是在运行时,我得到了ModuleNotFoundError。如何处理动态模块加载。请注意,这些插件/模块在构建过程中不可用。
编辑:添加了一些示例代码
interface.py
class Plugin:
def __init__(self):
pass
def doSomethingUsefull(self, a, b):
pass
main.py
import inspect
import pathlib
import os
from interface import Plugin
from importlib import import_module
def loadPlugins():
plugins_dir = os.path.join(os.getcwd(), "plugins")
for root, dirs, files in os.walk(plugins_dir):
for file in files:
modulename, ext = os.path.splitext(file)
if ext == ".py":
module = import_module("plugins." + modulename)
for name, klass in inspect.getmembers(module, inspect.isclass):
if klass.__module__ == "plugins." + modulename:
instance = klass()
if isinstance(instance, Plugin):
print("Plugin Call:", instance.doSomethingUsefull(3, 5))
break # not to list __pycache__ etc
loadPlugins()
plugins / test.py
from interface import Plugin
class TestPlugin(Plugin):
def __init__(self):
pass
def doSomethingUsefull(self, a, b):
return a * b
创建可执行文件后出现此错误:
Traceback (most recent call last):
File "main.py", line 24, in <module>
loadPlugins()
File "main.py", line 15, in loadPlugins
module = import_module("plugins." + modulename)
File "importlib/__init__.py", line 126, in import_module
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 941, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'plugins'
[3451] Failed to execute script main
这里也是一棵树:
.
├── interface.py
├── main
├── main.py
├── main.spec
└── plugins
└── test.py
当我使用python3 main.py
运行该应用程序时,得到以下输出:
Plugin Call: 15
答案 0 :(得分:0)
幸运的是我找到了解决方案。 我忘了提及我为pyinstaller使用了--onefile选项,其中应用程序正在sys._MEIPASS中而不是os getcwd()中查找模块。 当我不使用--onefile时,一切正常。