python - 如何使用 pyinstaller 在应用程序构建中加载插件?
问题描述
我有一个 python 应用程序,它在运行时将插件作为模块加载。
module = importlib.import_module("plugins." + modulename)
现在我想使用 pyinstaller 构建一个可执行文件,但在运行时我得到一个 ModuleNotFoundError。如何处理动态模块加载。需要明确的是,这些插件/模块在构建过程中不可用。
编辑:添加了一些示例代码
interface.py
class Plugin:
def __init__(self):
pass
def doSomethingUsefull(self, a, b):
pass
主文件
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()
插件/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
解决方案
幸运的是,我找到了解决方案。我忘了提到我已经为 pyinstaller 使用了 - - onefile 选项,其中应用程序在 sys._MEIPASS 而不是 os getcwd() 中寻找模块。当我不使用 - - onefile 时,一切正常。
推荐阅读
- android - Google play 测试购买
- laravel - 通过 Laravel API 路由
- php - Wordpress - 注册 WooCommerce 订单时如何防止 profile_update 挂钩触发?
- c - 是什么导致堆栈溢出?我该如何解决?
- php - 无法对两个中间件进行分组
- jquery - 无法在 TypeScript 中使用 `$(document).ready`
- macos - 在 macOS 和 MAMP 上运行 PHP Cron 作业
- qt - 在 QObject 派生类中实例化 QWidget 派生类
- sql - 找出表上的主键和外键是什么
- swift - 单击可可应用程序中的项目时如何保持dockMenu打开