Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Python应用程序捆绑为单个文件以支持附加组件或扩展?_Python_Py2exe_Software Distribution_Py2app_Pyinstaller - Fatal编程技术网

将Python应用程序捆绑为单个文件以支持附加组件或扩展?

将Python应用程序捆绑为单个文件以支持附加组件或扩展?,python,py2exe,software-distribution,py2app,pyinstaller,Python,Py2exe,Software Distribution,Py2app,Pyinstaller,有几种实用程序(都有不同的过程、限制和目标操作系统)用于获取Python包及其所有依赖项,并将它们转换为易于向客户提供的单一二进制程序: 我的情况更进一步:第三方开发人员将希望为我的应用程序编写插件、扩展或附加组件。当然,这是一个令人望而生畏的问题,Windows等平台上的用户如何最容易地安装插件或插件,使我的应用程序能够轻松发现它们已经安装。但除了这个基本问题之外,还有另一个问题:第三方开发人员如何将其扩展与扩展本身所需的任何库(可能是二进制模块,如lxml)捆绑在一起,从而使插件

有几种实用程序(都有不同的过程、限制和目标操作系统)用于获取Python包及其所有依赖项,并将它们转换为易于向客户提供的单一二进制程序:

我的情况更进一步:第三方开发人员将希望为我的应用程序编写插件、扩展或附加组件。当然,这是一个令人望而生畏的问题,Windows等平台上的用户如何最容易地安装插件或插件,使我的应用程序能够轻松发现它们已经安装。但除了这个基本问题之外,还有另一个问题:第三方开发人员如何将其扩展与扩展本身所需的任何库(可能是二进制模块,如lxml)捆绑在一起,从而使插件的依赖项在插件可用的同时可供导入


如何才能做到这一点?我的应用程序是否需要在磁盘上有自己的插件区域和自己的插件注册表才能使其易于处理?还是有一些我可以避免自己编写的通用机制,允许作为单个可执行文件分发的应用程序四处查看并查找也作为单个文件安装的插件?

您应该能够拥有一个插件目录,您的应用程序在运行时(或以后)扫描该目录以导入相关代码。下面是一个例子,它可以使用常规的.py或.pyc代码,甚至可以使用存储在zip文件中的插件(这样用户就可以将someplugin.zip放到“plugins”目录中,让它神奇地工作):

假设我有一个名为“foo.py”的插件,它位于一个名为“plugins”的目录中(在我的应用程序的基本目录中),它将为我的应用程序添加一个新功能。内容可能如下所示:

from plugin_stuff import Plugin

class Foo(Plugin):
    """An example plugin."""
    self.menu_entry = {'Tools': {'Foo': self.bar}}
    def bar(self):
        return "foo plugin!"
我可以在启动应用程序时初始化插件,如下所示:

plugin_dir = "%s/plugins" % os.getcwd()
plugin_list = get_plugins(plugin_dir)
init_plugin_system({'plugin_path': plugin_dir, 'plugins': plugin_list})
plugins = find_plugins()
plugin_menu_entries = []
for plugin in plugins:
    print "Enabling plugin: %s" % plugin.__name__
    plugin_menu_entries.append(plugin.menu_entry))
add_menu_entries(plugin_menu_entries) # This is an imaginary function
只要插件是.py或.pyc文件(假设它是针对所讨论的平台进行字节编译的),就应该可以工作。它可以是独立文件,也可以位于具有init.py的目录内,也可以位于具有相同规则的zip文件内

我怎么知道这是有效的?这就是我在中实现插件的方式。PyCI是一个web应用程序,但没有理由认为此方法不适用于常规的ol'GUI。对于上面的示例,我选择使用一个虚构的add_menu_entries()函数和一个插件对象变量,该变量可用于将插件的方法添加到GUI的菜单中


希望这个答案能帮助你建立自己的插件系统。如果您想确切了解它是如何实现的,我建议您下载PyCI源代码,并查看plugin_utils.py和plugins_enabled目录中的示例插件。

这里是使用插件的Python应用程序的另一个示例:。这里,插件只能是Python模块。

感谢您指出PyCl的方法!当插件作者想要捆绑依赖项时,比如我的问题提到的“lxml”库,他们会做什么?如果两个插件都需要“lxml”,但每个插件捆绑的版本略有不同,该怎么办?如果“lxml”有二进制部分,在Windows上生成DLL,而在Linux上生成DLL呢?插件作者可以在插件的基本路径中包含他们需要的任何依赖项。这是因为插件的路径是在导入之前添加到sys.path的。唯一需要注意的是,如果插件需要特定于平台的依赖关系,那么插件作者必须为他们愿意支持的每个架构提供一个包。我还想提到PyCI包含从插件目录中检索文件的方法(在Plugin()中)。因此,如果一个插件使用静态内容,那么即使该插件位于zip文件中,也可以提供该插件。
plugin_dir = "%s/plugins" % os.getcwd()
plugin_list = get_plugins(plugin_dir)
init_plugin_system({'plugin_path': plugin_dir, 'plugins': plugin_list})
plugins = find_plugins()
plugin_menu_entries = []
for plugin in plugins:
    print "Enabling plugin: %s" % plugin.__name__
    plugin_menu_entries.append(plugin.menu_entry))
add_menu_entries(plugin_menu_entries) # This is an imaginary function