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

Posted

技术标签:

【中文标题】无法在 Linux 上使用 pyinstaller 和 cefpython 创建可执行文件(ICU 数据的文件描述符无效)【英文标题】:failed to create executable with pyinstaller and cefpython on Linux (Invalid file descriptor to ICU data) 【发布时间】:2020-10-13 16:13:30 【问题描述】:

我有一些简单的 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")
+          )
 

我可以在 windows 上使用 python 成功编译我的应用程序 在具有 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 64bit,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.***.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

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

【问题讨论】:

【参考方案1】:

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

1- 在 CEFpython 中下载名为 hook-cefpython3.py 的 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 提供正确版本的挂钩文件。

【讨论】:

感谢您的回答,我们会尽快尝试。这看起来绝对比我的方法更干净 对我不起作用。您能否发布 pyinstaller / cefpython / python 的确切版本并检查它是否适合您? @gelonida:PyInstaller 4.1,cef:最后一个,它越来越旧,python 3.7(只是因为 cef 不支持较新的 Python)。现在我只是在 Windows 中测试(我上周来到这个页面,但在 Windows 中无效,所以我继续搜索)。但仍然没有太多测试(我还需要为其他操作系统构建)。 ——也许我错过了一点。星期一(上班)我应该可以验证。 通过我的问题示例和我尝试过的版本,我从来没有遇到过 Windows 问题。 (在 Windows 上它按预期工作)但正如我的问题中提到的:我使用了 PyInstaller 3.2.1 我猜是,更新版本的 PyInstaller 和 Windows 修复需要您的修复。不幸的是,它似乎无法修复 Linux。当我有更多时间时,我会尝试使用更新版本的 pyinstaller 和 Linux 进行修复。也许这种组合会奏效。 刚刚尝试使用 linux python3.5、cefpython3==66.0 和 pyinstaller==4.1(还有 pyinstaller==4.2)还是同样的错误。 :-(【参考方案2】:

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

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

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

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

并且可执行文件有效。

我确信还有一个更好的非暴力解决方案,但暂时我想回答一下,以防其他人也被卡住

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

【讨论】:

接受我自己的答案,因为一个多月没有出现其他答案。一旦出现更好的答案,将立即更改已接受的答案。 另见:github.com/pyinstaller/pyinstaller/issues/5400 @GiacomoCatenazzi 我试图理解讨论。我理解的好吗?这是正确的合成吗?仍然没有解决方案,但讨论仍在进行中,对 cefpython 的修复是解决这种情况的建议。 但还有其他解决方法:1- 从 cef 复制安装文件,2- 删除 python2 导入/条件 3- 调整规范文件以便读取挂钩。然后我们有一个工作版本。与您的解决方案相比,该解决方案适用于 Windows(它没有符号链接)。 @GiacomoCatenazzi 你能把这个作为答案发布,我会接受。我刚刚发布并接受了我的答案,因为没有比这更好的了。在问题从根本上解决之前,您的解决方案听起来已经更好了。【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

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

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

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

    pyinstaller --additional-hooks-dir 。

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

【讨论】:

谢谢。会尝试。但请注意,我遇到的问题只是 Linux

以上是关于无法在 Linux 上使用 pyinstaller 和 cefpython 创建可执行文件(ICU 数据的文件描述符无效)的主要内容,如果未能解决你的问题,请参考以下文章

PyInstaller Winerror3:系统无法找到指定的路径

pyinstaller打包在别的电脑上无法运行?

PyInstaller使用教程

使用 Fbs/PyInstaller 冻结我的应用程序导致在另一台电脑上启动时无法执行 pyi_rth_qt5plugins

PyInstaller 怎么在linux安装和使用

生成的 windows exe (pyinstaller) 无法加载 _cffi_backend