py2exe编译代码中未编译python插件的动态加载

py2exe编译代码中未编译python插件的动态加载,python,dynamic,plugins,Python,Dynamic,Plugins,我的Python应用程序是这样构造的,一些功能可以作为插件使用。插件架构目前非常简单:我有一个包含一些python模块的插件文件夹/包。我加载相关插件如下: plugin_name = blablabla try: module = __import__(plugin_name, fromlist='do_something') except ImportError: #some error handling ... 然后执行: try: loans = module.d

我的Python应用程序是这样构造的,一些功能可以作为插件使用。插件架构目前非常简单:我有一个包含一些python模块的插件文件夹/包。我加载相关插件如下:

plugin_name = blablabla
try:
    module = __import__(plugin_name, fromlist='do_something')
except ImportError:
   #some error handling ...
然后执行:

try:
    loans = module.do_something(id_t, pin_t)
except xxx:
    # error handling
我使用py2exe将应用程序编译为Windows二进制文件除了所有插件都包含在二进制文件中(并且必须包含在二进制文件中)之外,这一切都很正常。这不太实际,因为对于每个新插件,我都必须重新编译并发布我的应用程序的新版本。如果可以将一个新插件(即python文件)复制到某个应用程序插件文件夹中,并且我的应用程序可以动态地解释文件代码中的python代码,那就更好了

这样做的最佳方法是什么


(我想阅读所选插件文件的每一行,并对其应用一个。但是可能有更好的方法…

我建议您使用pkg\u资源入口点功能(来自setuptools/distribute)来实现插件发现和实例化:首先,这是一种标准方法;第二,它没有你提到的问题。扩展应用程序所要做的就是将一些插件打包到一个egg中,该egg声明一些入口点(一个egg可能声明许多插件),当您将该egg安装到python发行版中时,应用程序可以自动发现它声明的所有插件。您也可以将应用程序和“工厂”插件打包到同一个鸡蛋中,这非常方便。

我不确定您是否必须将插件文件放入zip库中。 这可能是因为您正在使用默认的py2exe打包脚本


您可以尝试使用compressed=False(如中所述),这将消除py2exe生成的library.zip,并可能允许您以“正常”的方式访问python模块(我猜想,您的插件是来自导入的python模块),而不是被迫将它们打包到zip或二进制文件中。

还可以导入外部文件。如果在应用程序上运行它,它将不会在可执行文件中打包这些文件。然后,您必须确保路径正确(也就是说,您的应用程序可以在正确的目录中找到磁盘上的模块),并且一切正常。

如果您不介意插件将作为.py文件发布,您可以执行以下操作。将所有插件放在“plugin”子目录下,并创建一个空的“\uuuu init\uuuu.py”。在运行时,它将导入包以及该目录中的所有模块。查看解释。。。但这是我最终使用的

def load_plugin(path):
    import imp
    """Load plugin from directory and return list of modules"""
    files = os.listdir( path )
    test = re.compile(".py$", re.IGNORECASE)          
    files = filter(test.search, files)                     
    filenameToModuleName = lambda f: os.path.splitext(f)[0]
    moduleNames = sorted(map(filenameToModuleName, files))
    f, filename, desc = imp.find_module('plugin')
    plugin = imp.load_module('plugin', f, filename, desc)
    modules = []

    #print moduleNames
    for m in moduleNames:
        # skip any files starting with '__', such as __init__.py
        if m.startswith('__'):
            continue
        try:
            f, filename, desc = imp.find_module(m, plugin.__path__)
            modules.append( imp.load_module(m, f, filename, desc))
        except ImportError:
            continue
    return modules

我发现了如何使用pyinstaller导入外部模块(在运行时位于编译的可执行文件之上)。 它表明,最初,可执行文件的路径自动添加到sys.path,但出于安全原因,他们在某个时候删除了该路径。 要重新启用此功能,请使用:

sys.path.append(os.path.dirname(sys.executable))
这将允许导入与可执行文件位于同一路径中的.py文件。
您可以将此行添加到运行时挂钩或主应用程序。

谢谢您的回答。但这不需要有人在他的计算机上安装python吗?(我提出的解决方案要求,现在我想起来了)您是对的,您的应用程序和外部插件的python安装应该是相同的。我同意这很烦人。这些模块是否可能加载编译版本中存在的类?