【问题标题】:Bundle CEFpython on PyInstaller with --onefile option使用 --onefile 选项在 PyInstaller 上捆绑 CEFpython
【发布时间】:2019-01-04 14:26:28
【问题描述】:

我有一个应用程序,其中有两个可执行文件:Flask-SocketIO-Server 和 CefPython 浏览器。我将这两个可执行文件与 PyInstaller 捆绑在一起。带有--onefile 选项的Flask-Server 和带有--onedir 选项的cefpython,因为我无法使用--onefile。现在我决定只对这两种代码(Flask 和 CEFpython)都可执行,所以我的烧瓶服务器有代码来运行 CEF 图形用户界面:

if __name__ == '__main__':

    if len(sys.argv) > 1 and sys.argv[1] == 'dev':
        print "Running Flask-SocketIO on dev mode"
    else:
        print "Running Flask-SocketIO on production mode"
        path = os.getcwd()
        gui_path = path + '\\display_react\\display_react.exe'
        print 'Running Graphical User Interface...'
        thread.start_new_thread(display_react.main, ())  # Baterias
        print 'Initializing server'


    socketio.run(app, debug=False)

代码工作正常,但是当我尝试将此代码与带有 --onefile 选项的 PyInstaller 捆绑在一起时,生成的可执行文件不起作用会导致某些 CEF 依赖项。 这里是运行 Pyinstaller 时的错误:

在生产模式下运行 Flask-SocketIO 运行图形用户 接口...初始化服务器 [wxpython.py] CEF Python 57.1 [wxpython.py] Python 2.7.14 64 位 [wxpython.py] wxPython 4.0.1 msw (凤凰)[0727/125110.576:ERROR:main_delegate.cc(684)] 无法加载 用于 en-US 的语言环境 pak [0727/125110.576:ERROR:main_delegate.cc(691)] 无法加载 cef.pak [0727/125110.578:ERROR:main_delegate.cc(708)] 无法加载 cef_100_percent.pak [0727/125110.582:ERROR:main_delegate.cc(717)] 无法加载 cef_200_percent.pak [0727/125110.582:ERROR:main_delegate.cc(726)] 无法加载 cef_extensions.pak [0727/125110.648:ERROR:content_client.cc(269)] 没有数据资源 可用于 id 20418 [0727/125110.648:ERROR:content_client.cc(269)] 没有可用于 id 20419 的数据资源 [0727/125110.650:ERROR:content_client.cc(269)] 没有数据资源 可用于 id 20420 [0727/125110.655:ERROR:content_client.cc(269)] 没有可用于 id 20421 的数据资源 [0727/125110.656:ERROR:content_client.cc(269)] 没有数据资源 可用于 id 20422 [0727/125110.656:ERROR:content_client.cc(269)] 没有可用于 id 20417 的数据资源 [0727/125110.680:ERROR:extension_system.cc(72)] 解析失败 扩展清单。 C:\Users\Ricardo\AppData\Local\Temp_MEI95~1\display_react.py:118: wxPyDeprecationWarning:调用已弃用的项 EmptyIcon。采用 :class:Icon 代替

这里是我正在使用的 .spec 文件:

# -*- mode: python -*-

block_cipher = None

def get_cefpython_path():
    import cefpython3 as cefpython

    path = os.path.dirname(cefpython.__file__)
    return "%s%s" % (path, os.sep)

cefp = get_cefpython_path()


a = Analysis(['server.py'],
             pathex=['C:\\Users\\Ricardo\\addvolt-scanning-tool\\backend'],
             binaries=[],
             datas=[('PCANBasic.dll', '.'), ('o.ico', '.')], #some dlls i need for flask
             hiddenimports=['engineio.async_gevent'], #engineio hidden import for Flask usage
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas + [('locales/en-US.pak', '%s/locales/en-US.pak' % cefp, 'DATA')], # my try to fix that missing dependencies
          name='server',
          debug=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True )

编辑:已解决

感谢@cztomczak,我得到了这个工作。问题不在 PyInstaller 上,而是在 wxpython.py 寻找语言环境、资源和子进程的过程中。尽管所有文件都在“temp/dir/_MEIxxx”上,但 wxpython 正在可执行文件的目录中寻找这些文件。所以我通知代码在临时目录中查找这些文件的方法是:

dir_temp = tempfile.gettempdir()
files = []
for i in os.listdir(dir_temp):
    if os.path.isdir(os.path.join(dir_temp,i)) and '_MEI' in i:
        files.append(i)
dir_temp = dir_temp + str(files[0])
dir_temp = os.path.join(dir_temp, str(files[0]))
dir_temp_locale = os.path.join(dir_temp, 'locales')
dir_temp_subprocess = os.path.join(dir_temp_subprocess, 'subprocess.exe')

print dir_temp
dir_temp = dir_temp.replace("\\", "\\\\")
print dir_temp
print dir_temp_locale
dir_temp_locale = dir_temp_locale.replace("\\", "\\\\")
print dir_temp_locale
dir_temp_supbprocess = dir_temp_subprocess.replace("\\", "\\\\")
print dir_temp_subprocess

...

settings = {'auto_zooming': '-2.5', 'locales_dir_path': dir_temp_locale, 'resources_dir_path': dir_temp, 'browser_subprocess_path': dir_temp_subprocess}

我必须这样做,因为在 temp (_MEIxxxx) 上创建的文件夹的名称总是在变化。也许我将来会遇到问题,因为如果应用程序崩溃,_MEIxx 文件夹将不会被删除,如果我尝试重新运行可执行文件,这段代码将有两个 _MEI 文件夹,并且可能根本无法工作,直到有人清理临时目录。

所以,恢复... 将应用程序捆绑到一个文件中: - 在 Python27/envs/libs/site-package/Pyinstaller/hooks 上粘贴 hook-cefpython3.py(包中提供) - 使用 --onefile 选项运行 Pyinstaller - 告诉cefpython代码locale、resource和subprocess在哪里(locale_dir_path, resource_dir_path, browser_subprocess_path)

【问题讨论】:

    标签: python exe pyinstaller flask-socketio cefpython


    【解决方案1】:

    我遇到了类似的问题,发现使用 _MEIPASS 环境变量是一个更优雅的解决方案。

    import cefpython
    import os
    import sys
    
    if hasattr(sys, '_MEIPASS'):
        # settings when packaged
        settings = {'locales_dir_path': os.path.join(sys._MEIPASS, 'locales'),
                    'resources_dir_path': sys._MEIPASS,
                    'browser_subprocess_path': os.path.join(sys._MEIPASS, 'subprocess.exe'),
                    'log_file': os.path.join(sys._MEIPASS, 'debug.log')}
    else:
        # settings when unpackaged
        settings = {}
    
    cefPython.Initialize(settings=settings)
    

    【讨论】:

      【解决方案2】:

      我猜你得到的错误是因为你的规范文件没有包含所有必要的 CEF 二进制文件。有一个官方的 pyinstaller 示例,您可以使用和修改以使用 --onefile 选项:https://github.com/cztomczak/cefpython/blob/master/examples/pyinstaller/README-pyinstaller.md

      【讨论】:

      • 好吧,我尝试运行 pyinstaller 的示例,当 pyinstaller 访问 hook-cefpython3.py 时,它给出了一个错误:'AssertionError: Missing cefpython3 Cython modules'。你知道可能是什么原因吗?非常感谢您的帮助。
      • 您系统上的cefpython3包的内容似乎被修改了。那里有多个 .pyd 文件。断言在这里:github.com/cztomczak/cefpython/blob/master/examples/pyinstaller/…
      • @RicardoGoncalves 检查 CEFPYTHON3_DIR 的设置。
      • 非常感谢!就是这样。 CFPYTHON3_DIR 是:c:\xxx\xxx\envs\inst_exe\scripts\Lib\site-packages\cefpython3,而不是 c:\xxx\xxx\envs\inst_exe\Lib\site-packages\cefpython3。现在可以了。现在我将尝试修改 .spec 文件以生成单个可执行文件。再次感谢您的帮助和令人惊叹的软件包。
      • 我已编辑 .spec 文件以生成一个文件。虽然生成成功,但由于同样的问题,它没有运行:缺少 locale pak、cef.pak、cef_100.pak 等。基本上是 locale 文件夹和 .pak 文件。这里我的 .spec 修改了(只有我改变的部分,deletec Collect() 并编辑了 Exe()): exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, name='cefapp' , debug=DEBUG, strip=False, upx=False, console=DEBUG, icon="../resources/wxpython.ico")。我仍在尝试在您的 pyinstaller 示例中执行此操作
      猜你喜欢
      • 2011-12-02
      • 2012-12-06
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      相关资源
      最近更新 更多