python - 使用 pyinstaller 打包一个 twistd 插件

标签 python twisted pyinstaller twistd

我创建了一个不错的 python Twisted 应用程序,其中包含一个用于 twistd 运行器的插件,如 Twisted 文档中所述:http://twistedmatrix.com/documents/current/core/howto/tap.html .我在使用 PyInstaller 打包时遇到问题:在执行卡住的应用程序期间找不到我的 twistd 插件。

为了发布我的项目,我使用 twistd runner 模块创建了自己的顶级启动脚本,例如

#!/usr/bin/env python
from twisted.scripts.twistd import run
from sys import argv
argv[1:] = [
  '--pidfile', '/var/run/myapp.pid',
  '--logfile', '/var/run/myapp.log',
  'myapp_plugin'
]
run()

接下来,我使用 PyInstaller 将其卡住为单个目录部署。执行上面的卡住脚本失败,因为它找不到我的 twistd 插件(为简洁起见进行了编辑):

~/pyinstall/dist/bin/mystartup?16632/twisted/python/modules.py:758:
UserWarning: ~/pyinstall/dist/mystartup?16632 (for module twisted.plugins)
not in path importer cache (PEP 302 violation - check your local configuration).

~/pyinstall/dist/bin/mystartup: Unknown command: myapp_plugin

通常,Twistd 检查 Python 系统路径以在 twisted/plugins/myapp_plugin.py 中发现我的插件。如果我在启动脚本中打印 twistd 插件列表,则该列表在 PyInstaller 生成的可执行文件中为空,例如

from twisted.plugin import IPlugin, getPlugins
plugins = list(getPlugins(IPlugin))
print "Twistd plugins=%s" % plugins

我使用了一些默认的 PyInstaller 规范文件,没有指定隐藏的导入或导入 Hook 。

我喜欢 twistd 的日志记录、pid 文件等功能,所以我想避免不得不完全放弃 twistd runner 来规避插件问题。 有没有办法确保在卡住的可执行文件中找到我的 twistd 插件?

最佳答案

我通过对一些扭曲代码进行逆向工程找到了解决方法。在这里,我对插件导入进行了硬编码。这对我来说适用于 PyInstaller。

#!/usr/bin/env python
import sys

from twisted.application import app
from twisted.scripts.twistd import runApp, ServerOptions

import myapp_plugin as myplugin


plug = myplugin.serviceMaker


class MyServerOptions(ServerOptions):
    """
    See twisted.application.app.ServerOptions.subCommands().
    Override to specify a single plugin subcommand and load the plugin
    explictly.
    """
    def subCommands(self):
        self.loadedPlugins = {plug.tapname:plug}
        yield (plug.tapname,
               None,
               # Avoid resolving the options attribute right away, in case
               # it's a property with a non-trivial getter (eg, one which
               # imports modules).
               lambda plug=plug: plug.options(),
               plug.description)

    subCommands = property(subCommands)


def run():
    """
    Replace twisted.application.app.run()
    To use our ServerOptions.
    """
    app.run(runApp, MyServerOptions)


sys.argv[1:] = [
    '--pidfile', '/var/run/myapp.pid',
    '--logfile', '/var/run/myapp.log',
    plug.tapname] + sys.argv[1:]

run()

关于python - 使用 pyinstaller 打包一个 twistd 插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10181868/

相关文章:

python - Twisted/tkinter 程序在退出时崩溃

pyinstaller - 使用 PyInstaller 编写的程序现在被 AVG 视为特洛伊木马

python - 导出单个 .exe 时,PyInstaller 卡在 "Building PKG ..."上

python - 如何使用Python代码在Azure上创建虚拟机?

python - 使用 Python 创建一个简单的网页,其中模板内容是根据查询从数据库(或 pandas 数据框)填充的

python - conn.send ('Hi' .encode()) BrokenPipeError : [Errno 32] Broken pipe (SOCKET)

python - 编写要导入的轻量级客户端函数的好方法 Twisted Python

python - Twisted DeferredList 仅在一半的时间内运行其回调

python - 分组/汇总数据的秘诀?

pyinstaller - 如何在 pyinstaller --add-binary 之后使用捆绑程序?