首页 > 解决方案 > 如何使用 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

标签: pythonpyinstaller

解决方案


幸运的是,我找到了解决方案。我忘了提到我已经为 pyinstaller 使用了 - - onefile 选项,其中应用程序在 sys._MEIPASS 而不是 os getcwd() 中寻找模块。当我不使用 - - onefile 时,一切正常。


推荐阅读