无法在 Linux 上使用 pyinstaller 和 cefpython 创建可执行文件(ICU 数据的文件描述符无效)

failed to create executable with pyinstaller and cefpython on Linux (Invalid file descriptor to ICU data)

我有一些简单的 cefpython 代码打开 url 并且正在尝试使用 pyinstaller 创建一个独立的可执行文件:

我将文件从 https://github.com/cztomczak/cefpython/tree/master/examples/pyinstaller 复制到名为 pyinstaller

的目录

我对 pyinstaller.spec

做了以下小改动
+SECRET_CIPHER = ""
...
-    ["../wxpython.py"],
+    ["../hello.py"],
...
-          icon="../resources/wxpython.ico")
+          )
 

我可以使用 python 在 windows 上成功编译我的应用程序 在装有 python 3.5.4 64 位和以下 virtualenv 的同一台机器上:

cefpython3==66.0
future==0.18.2
PyInstaller==3.2.1
pypiwin32==223
pywin32==228

我也可以用 python 3.6.4 64 和以下 virtualenv 编译 windows:

altgraph==0.17
cefpython3==66.0
future==0.18.2
macholib==1.14
pefile==2019.4.18
PyInstaller==3.3.1
pyinstaller-hooks-contrib==2020.9
pypiwin32==223
pywin32==228
pywin32-ctypes==0.2.0

在 Linux 上编译也能正常工作,但可执行文件无法运行。

我得到以下输出和错误:

CEF Python 66.0
Chromium 66.0.3359.181
CEF 3.3359.1774.gd49d25f
Python 3.5.2 64bit
[1013/180954.001980:ERROR:icu_util.cc(133)] Invalid file descriptor to ICU data received.
Trace/breakpoint trap (core dumped)

版本是 python 3.5.2 64 位,virtualenv 是:

cefpython3==66.0
pkg-resources==0.0.0
PyInstaller==3.2.1

可能是什么原因?

我尝试编译的代码如下:

import platform
import sys
from cefpython3 import cefpython as cef


def check_versions():
    ver = cef.GetVersion()
    print("CEF Python {ver}".format(ver=ver["version"]))
    print("Chromium {ver}".format(ver=ver["chrome_version"]))
    print("CEF {ver}".format(ver=ver["cef_version"]))
    print("Python {ver} {arch}".format(
           ver=platform.python_version(),
           arch=platform.architecture()[0]))
    assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this"


def main(url="https://www.whosebug.com"):
    sys.excepthook = cef.ExceptHook
    check_versions()
    settings = {}
    switches = {}
    browser_settings = {}
    cef.Initialize(settings=settings, switches=switches)
    cef.CreateBrowserSync(
        url=url,
        window_title="CEF_HELLO: ",
        settings=browser_settings,
        )
    cef.MessageLoop()
    cef.Shutdown()


if __name__ == "__main__":
    main()

附录:2020-10-14:

linux 与其他版本相同的错误: 到目前为止,我尝试了 python 3.5 和 3.7

有人成功创建了可执行文件吗? 我可能是,这只是示例项目及其配置的问题?

这不是我真正愿意接受的答案,但它至少是一种解决方案并包含信息,可能会导致更好的修复、更好的答案。

在使用 strace 调试后我发现,可执行文件搜索了许多文件,例如 icudtl.datv8_context_snapshot.binlocales/* 'dist/cefapp/cefpython3but were copied todist/cefapp/`

一个丑陋的解决方法是在编译后执行以下操作

cd dist/cefapp/cefpython3
ln -s ../* .

并且可执行文件有效。

我相信还有更好的 non-brute-force 解决方案,但暂时我想回答一下以防其他人也被卡住

可能这可以在规范文件中修复,但是我们是否需要一个用于 linux 的规范文件和一个用于 windows 的规范文件? 也许还有一个选项可以让可执行文件在更高一级搜索这些文件?

作为替代方案,可以在 PyInstaller bug 5400 中找到解决方案 这里的步骤:

1- 在名为 hook-cefpython3.py 的 CEFpython 中下载 PyInstaller 帮助程序: https://github.com/cztomczak/cefpython/tree/master/examples/pyinstaller 并放入你项目的根目录

2- 在该文件中,替换行:

from PyInstaller.compat import is_win, is_darwin, is_linux, is_py2

与:

from PyInstaller.compat import is_win, is_darwin, is_linux
is_py2 = False

3- 在您的 PyInstaller .spec 文件中,将 '.' 添加到 hookspath,例如hookspath=['.']。我认为也可以将其添加为 PyInstaller 命令行选项。

这些步骤应该可以解决问题,直到 CEFPython 交付正确版本的挂钩文件。

要解决这个问题,您需要在规范文件中进行设置:

hookspath=[r'YOUR_ENV_SITE_PACKAGES\cefpython3\examples\pyinstaller\']

然后重建,你会在正确的地方得到东西。

以下步骤为我解决了 Windows 10、Python 3.9.5 32 位、PyInstaller 4.3 和 CEFPython 66.1 上的问题:

  1. 下载hook-cefpython3.py file from here并将其放入您的项目根目录。

  2. 运行 pyinstaller 命令像往常一样,但添加了 --additional-hooks-dir . 命令行选项,因此命令将如下所示:

    pyinstaller --additional-hooks-dir 。 <主要-file.py>

与此处的其他答案相反,此 anser 既不需要更改 pyinstaller 规范文件中的 hookspath 指令,也不需要更改下载的 hook-cefpython3.py 文件。