Python pygst+;OSX下的pyinstaller

Python pygst+;OSX下的pyinstaller,python,pyinstaller,pygst,Python,Pyinstaller,Pygst,我目前正在尝试捆绑这个死气沉沉的简单python脚本(player.py): 使用pyinstaller(2.1.0-dev)进入OSX(我的机器运行Mountain Lion)应用程序 我的目标是创建一个可以轻松分发的.app包。我还可以要求最终用户安装GStreamer SDK,即使我的主要目标是一个自包含的应用程序 等级库文件如下(player.spec): 到目前为止,我尝试了两种策略: macports:python(2.7.2)、pygst(0.10)、gst插件-* 系统pytho

我目前正在尝试捆绑这个死气沉沉的简单python脚本(player.py):

使用pyinstaller(2.1.0-dev)进入OSX(我的机器运行Mountain Lion)应用程序

我的目标是创建一个可以轻松分发的.app包。我还可以要求最终用户安装GStreamer SDK,即使我的主要目标是一个自包含的应用程序

等级库文件如下(player.spec):

到目前为止,我尝试了两种策略:

  • macports:python(2.7.2)、pygst(0.10)、gst插件-*
  • 系统python,GStreamer 0.10 SDK(框架)
  • 在这两种情况下,我都可以成功运行脚本

    但是,当我尝试运行捆绑的可执行文件时,会得到以下结果:

  • (Macports)
  • 显示部分GST调试日志:

    ~/devel/t/simple/dist/player > GST_DEBUG=4 ./player
    [..]
    0:00:00.113260000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:573:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Plugin 'playback' feature 'playbin2' typename : 'GstElementFactory'
    0:00:00.113286000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:621:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Element factory : 'Player Bin 2' with npadtemplates=0
    0:00:00.113300000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:649:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Reading 2 Interfaces at address 0x101971191
    0:00:00.113318000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistry.c:558:gboolean gst_registry_add_feature(GstRegistry *, GstPluginFeature *):<registry0> adding feature 0x10097da20 (playbin2)
    0:00:00.113332000  8313    0x1001b1a00 DEBUG        GST_REFCOUNTING gstobject.c:844:gboolean gst_object_set_parent(GstObject *, GstObject *):<playbin2> set parent (ref and sink)
    0:00:00.113346000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:709:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Added feature playbin2, plugin 0x100975be0 playback
    [..]
    0:00:00.242584000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:106:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loading plugin for feature 0x10097da20; 'playbin2'
    0:00:00.242620000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:110:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loading plugin playback
    0:00:00.242632000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:1293:GstPlugin *gst_plugin_load_by_name(const gchar *): looking up plugin playback in default registry
    0:00:00.242662000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:1296:GstPlugin *gst_plugin_load_by_name(const gchar *): loading plugin playback from file /opt/local/lib/gstreamer-0.10/libgstplaybin.so
    0:00:00.242677000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:737:GstPlugin *gst_plugin_load_file(const gchar *, GError **): attempt to load plugin "/opt/local/lib/gstreamer-0.10/libgstplaybin.so"
    0:00:00.248338000  8297    0x1001b1a00 INFO      GST_PLUGIN_LOADING gstplugin.c:859:GstPlugin *gst_plugin_load_file(const gchar *, GError **): plugin "/opt/local/lib/gstreamer-0.10/libgstplaybin.so" loaded
    0:00:00.248374000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:115:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loaded plugin playback
    0:00:00.248390000  8297    0x1001b1a00 INFO      GST_PLUGIN_LOADING gstpluginfeature.c:145:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): Tried to load plugin containing feature 'playbin2', but feature was not found.
    0:00:00.248402000  8297    0x1001b1a00 WARN     GST_ELEMENT_FACTORY gstelementfactory.c:410:GstElement *gst_element_factory_create(GstElementFactory *, const gchar *):<playbin2> loading plugin containing feature player returned NULL!
    0:00:00.248412000  8297    0x1001b1a00 INFO     GST_ELEMENT_FACTORY gstelementfactory.c:472:GstElement *gst_element_factory_make(const gchar *, const gchar *):<playbin2> couldn't create instance!
    Traceback (most recent call last):
      File "<string>", line 33, in <module>
      File "<string>", line 11, in __init__
    gst.ElementNotFoundError: playbin2
    
    它就挂在这里。如果我通过活动监视器对流程进行采样,我会得到以下结果:

    [..]
    _wrap_gst_element_factory_make  (in gst._gst.so)
    gst_element_factory_make  (in libgstreamer-0.10.0.dylib)
    gst_element_factory_create  (in libgstreamer-0.10.0.dylib)
    gst_plugin_feature_load  (in libgstreamer-0.10.0.dylib)
    gst_plugin_load_by_name  (in libgstreamer-0.10.0.dylib)
    gst_plugin_load_file  (in libgstreamer-0.10.0.dylib)
    gst_plugin_register_func  (in libgstreamer-0.10.0.dylib)
    plugin_init  (in libgstplaybin.so)
    gst_play_bin2_plugin_init  (in libgstplaybin.so)
    gst_pipeline_get_type  (in libgstreamer-0.10.0.dylib)
    gst_bin_get_type  (in libgstreamer-0.10.0.dylib)
    gst_child_proxy_get_type  (in libgstreamer-0.10.0.dylib)
    gst_object_get_type  (in libgstreamer-0.10.0.dylib)
    g_once_init_enter  (in libglib-2.0.0.dylib)
    g_cond_wait  (in libglib-2.0.0.dylib)
    _pthread_cond_wait  (in libsystem_c.dylib)
    __psynch_cvwait  (in libsystem_kernel.dylib)
    

    一个提示将不胜感激

    我终于有了以下设置的工作解决方案:

    • macports(python@2.7.3、py27-gst-python@0.10.22、gstreamer010@0.10.36)
    • pyinstaller 2.1-dev(ccb6f3d3d924a0dc2f9e92aa6278c28a2d743d39)
    • OSX 10.8.3
    pyinstaller规范文件(player.spec): _gst.so挂钩(挂钩gst.\u gst.py): 我为gst创建了一个非常原始的钩子。我试图将它放在本地目录中,通过分析对象的hookspath参数引用它,但我不明白pyinstaller为什么会忽略它。因此,我将其移动到/path/to/pyinstaller/pyinstaller/hooks文件夹:

    pyinstaller负责计算插件的依赖关系树,将.sos和依赖的dylib一起复制到位,最后将两者的mach'o头弄乱

    我还创建了一个空文件/path/to/pyinstaller/pyinstaller/hooks/hook-gst.py,以阻止pyinstaller抱怨缺少父钩子。而且,无论如何,钩子代码可以直接转到hook-gst.py

    运行时钩子文件(rthook.py) 最后,我添加了一个在分析对象上引用的运行时钩子文件,该文件设置了帮助gstreamer定位插件的环境变量。此代码在player.py之前的捆绑可执行文件上执行(按照设置pyinstaller的方式执行,感谢他们的宝贵提示):


    这不是一个答案,而是一条评论:安装MacPorts way意味着您将不得不结束,或者要求用户安装,不仅仅是GStreamer,还包括GStreamer或Python的所有依赖项。这并非不可能,但可能会非常痛苦。另一方面,使用system Python创建一个完全独立的构建(尤其是在比您更旧的操作系统版本上工作的构建)也会很痛苦。此外,您是否尝试过在上询问GStreamer、查看钩子集合、检查相关的bug报告等。?SO上有人在Mac上使用PyInstaller打包GStreamer的几率可能比PyInstaller邮件列表上有人在MacPorts上打包GStreamer的几率要低得多,按照Kivy这样的打包方法,我已经引入了所有相关的库。这部分是由pyinstaller完成的(与python扩展的DEP有关),我创建了一组脚本来检查plugins.sos并解决依赖关系,将它们从macports的lib路径复制到打包文件夹,修复dylibs路径(使用来自gstreamer cerbero工具集的osxrelocator.py)。无论如何,我不明白为什么在复制插件之前就不能在我的系统上加载插件。我检查了hooks集合,特别是pyqt,它成功地引入了插件,还有kivy自定义hooks,但我无法完全理解它们的方式。我将在第一站再次尝试,并最终遵循您关于PyInstaller的建议。谢谢酷!如果您还没有这样做,我仍然建议您使用
    PyInstaller
    打开一个hooks问题,将其作为补丁提交,和/或在邮件列表上开始讨论。至少,您可能会让有PyInstaller钩子经验的人检查您所做的工作,并验证您做的一切都是正确的。
    ~/devel/t/simple/dist/player > GST_DEBUG=4 ./player
    [..]
    0:00:00.113260000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:573:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Plugin 'playback' feature 'playbin2' typename : 'GstElementFactory'
    0:00:00.113286000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:621:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Element factory : 'Player Bin 2' with npadtemplates=0
    0:00:00.113300000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:649:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Reading 2 Interfaces at address 0x101971191
    0:00:00.113318000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistry.c:558:gboolean gst_registry_add_feature(GstRegistry *, GstPluginFeature *):<registry0> adding feature 0x10097da20 (playbin2)
    0:00:00.113332000  8313    0x1001b1a00 DEBUG        GST_REFCOUNTING gstobject.c:844:gboolean gst_object_set_parent(GstObject *, GstObject *):<playbin2> set parent (ref and sink)
    0:00:00.113346000  8313    0x1001b1a00 DEBUG           GST_REGISTRY gstregistrychunks.c:709:gboolean gst_registry_chunks_load_feature(GstRegistry *, gchar **, gchar *, GstPlugin *): Added feature playbin2, plugin 0x100975be0 playback
    [..]
    0:00:00.242584000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:106:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loading plugin for feature 0x10097da20; 'playbin2'
    0:00:00.242620000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:110:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loading plugin playback
    0:00:00.242632000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:1293:GstPlugin *gst_plugin_load_by_name(const gchar *): looking up plugin playback in default registry
    0:00:00.242662000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:1296:GstPlugin *gst_plugin_load_by_name(const gchar *): loading plugin playback from file /opt/local/lib/gstreamer-0.10/libgstplaybin.so
    0:00:00.242677000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstplugin.c:737:GstPlugin *gst_plugin_load_file(const gchar *, GError **): attempt to load plugin "/opt/local/lib/gstreamer-0.10/libgstplaybin.so"
    0:00:00.248338000  8297    0x1001b1a00 INFO      GST_PLUGIN_LOADING gstplugin.c:859:GstPlugin *gst_plugin_load_file(const gchar *, GError **): plugin "/opt/local/lib/gstreamer-0.10/libgstplaybin.so" loaded
    0:00:00.248374000  8297    0x1001b1a00 DEBUG     GST_PLUGIN_LOADING gstpluginfeature.c:115:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): loaded plugin playback
    0:00:00.248390000  8297    0x1001b1a00 INFO      GST_PLUGIN_LOADING gstpluginfeature.c:145:GstPluginFeature *gst_plugin_feature_load(GstPluginFeature *): Tried to load plugin containing feature 'playbin2', but feature was not found.
    0:00:00.248402000  8297    0x1001b1a00 WARN     GST_ELEMENT_FACTORY gstelementfactory.c:410:GstElement *gst_element_factory_create(GstElementFactory *, const gchar *):<playbin2> loading plugin containing feature player returned NULL!
    0:00:00.248412000  8297    0x1001b1a00 INFO     GST_ELEMENT_FACTORY gstelementfactory.c:472:GstElement *gst_element_factory_make(const gchar *, const gchar *):<playbin2> couldn't create instance!
    Traceback (most recent call last):
      File "<string>", line 33, in <module>
      File "<string>", line 11, in __init__
    gst.ElementNotFoundError: playbin2
    
    ~/devel/t/simple/dist/player > ./player 
    ** Message: pygobject_register_sinkfunc is deprecated (GstObject)
    player.py:11: Warning: cannot register existing type `GstObject'
    player.py:11: Warning: g_once_init_leave: assertion `result != 0' failed
    player.py:11: Warning: gtype.c:2720: You forgot to call g_type_init()
    
    [..]
    _wrap_gst_element_factory_make  (in gst._gst.so)
    gst_element_factory_make  (in libgstreamer-0.10.0.dylib)
    gst_element_factory_create  (in libgstreamer-0.10.0.dylib)
    gst_plugin_feature_load  (in libgstreamer-0.10.0.dylib)
    gst_plugin_load_by_name  (in libgstreamer-0.10.0.dylib)
    gst_plugin_load_file  (in libgstreamer-0.10.0.dylib)
    gst_plugin_register_func  (in libgstreamer-0.10.0.dylib)
    plugin_init  (in libgstplaybin.so)
    gst_play_bin2_plugin_init  (in libgstplaybin.so)
    gst_pipeline_get_type  (in libgstreamer-0.10.0.dylib)
    gst_bin_get_type  (in libgstreamer-0.10.0.dylib)
    gst_child_proxy_get_type  (in libgstreamer-0.10.0.dylib)
    gst_object_get_type  (in libgstreamer-0.10.0.dylib)
    g_once_init_enter  (in libglib-2.0.0.dylib)
    g_cond_wait  (in libglib-2.0.0.dylib)
    _pthread_cond_wait  (in libsystem_c.dylib)
    __psynch_cvwait  (in libsystem_kernel.dylib)
    
    # -*- mode: python -*-
    import os
    import pygst
    pygst.require('0.10')
    
    a = Analysis(['rthook.py', 'player.py'],
                 pathex=[os.curdir],
                 hiddenimports=[],
                 hookspath=None,
                 runtime_hooks=None)
    pyz = PYZ(a.pure)
    exe = EXE(pyz,
              a.scripts,
              exclude_binaries=True,
              name='player',
              debug=False,
              strip=None,
              upx=True,
              console=True )
    coll = COLLECT(exe,
                   a.binaries,
                   a.zipfiles,
                   a.datas,
                   strip=None,
                   upx=True,
                   name='player')
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import os
    
    GST_PLUGINS = '/opt/local/lib/gstreamer-0.10/'
    
    def hook(mod):
        for f in [so for so in os.listdir(GST_PLUGINS) if so[-3:].lower() == '.so']:
            mod.binaries.append((os.path.join('gst-plugins', f),
                    os.path.join(GST_PLUGINS, f),
                    'BINARY'))
    
        return mod
    
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import os
    import sys
    
    if hasattr(sys, '_MEIPASS'):
        # PyInstaller >= 1.6
        root = sys._MEIPASS
    elif '_MEIPASS2' in environ:
        # PyInstaller < 1.6 (tested on 1.5 only)
        root = os.environ['_MEIPASS2']
    else:
        root = os.path.dirname(sys.argv[0])
    
    os.chdir(root)
    
    os.environ['GST_REGISTRY_FORK'] = 'no'
    os.environ['GST_PLUGIN_PATH'] = os.path.join(root, 'gst-plugins')
    
    $ /path/to/pyinstaller/pyinstaller.py player.spec