_memimporter 还存在于 py2exe 中吗?

问题描述 投票:0回答:1

我最近才开始使用 py2exe,我想将 py2exe 与 MINGW64 Python3 程序(和相应的库)一起使用。但是,我尝试的第一个示例未能构建。

之后,我找到了https://www.py2exe.org/index.cgi/TroubleshootingImportErrors页面,其中注明:

检查 zipextimporter 是否在您的系统上运行

zipextimporter 是 py2exe 的启动组件,可能会导致问题。要调试它,您将需要 _memimporter.pyd 二进制模块。这些模块可以在您的 Python 版本的二进制 py2exe 发行版中找到(我使用 7Zip 解压 .exe 发行版)。

还有一个测试脚本,但它是Python 2(该页面的最后更新时间是2011-01-07);所以我将其转换为 Python 3 语法:

import zipextimporter
zipextimporter.install()

import sys
sys.path.insert(0, "lib.zip")

import _socket
print(_socket)
# <module '_socket' from 'lib.zip\_socket.pyd'>
print(_socket.__file__)
# 'lib.zip\\_socket.pyd'
print(_socket.__loader__)
# <ZipExtensionImporter object 'lib.zip'>
# Reloading also works correctly:
print(_socket is reload(_socket))
# True

但是当我运行它时,我得到:

$ python3 test_zipextimporter.py
Traceback (most recent call last):
  File "D:/msys64/tmp/test_zipextimporter.py", line 1, in <module>
    import zipextimporter
  File "D:/msys64/mingw64/lib/python3.11/site-packages/zipextimporter.py", line 51, in <module>
    import _memimporter
ModuleNotFoundError: No module named '_memimporter'

所以,正如上面的注释所说,我需要一个

_memimporter.pyd
二进制模块;直接包里没有这个文件:

$ pacman -Ql mingw-w64-x86_64-python-py2exe | grep _mem
$

但是,注释还指出“这些模块可以在您的 Python 版本的二进制 py2exe 发行版中找到(我使用 7Zip 解压 .exe 发行版)。”目前包中有这些二进制文件:

$ pacman -Ql mingw-w64-x86_64-python-py2exe | grep '\.exe\|\.dll'
mingw-w64-x86_64-python-py2exe /mingw64/lib/python3.11/site-packages/py2exe/resources.dll
mingw-w64-x86_64-python-py2exe /mingw64/lib/python3.11/site-packages/py2exe/run-py311-mingw_x86_64.exe
mingw-w64-x86_64-python-py2exe /mingw64/lib/python3.11/site-packages/py2exe/run_ctypes_dll-py311-mingw_x86_64.dll
mingw-w64-x86_64-python-py2exe /mingw64/lib/python3.11/site-packages/py2exe/run_w-py311-mingw_x86_64.exe

这些都不能用

unzip -l
来列出;但它们可以用
7z l
列出 - 不幸的是,我没有看到任何类似
_memimporter.pyd
的东西 - 两个 .exe 都显示了这种文件结构:

$ 7z l /mingw64/lib/python3.11/site-packages/py2exe/run_w-py311-mingw_x86_64.exe
...
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-12-27 10:55:20 .....        24064        24064  .text
2023-12-27 10:55:20 .....         1024         1024  .data
2023-12-27 10:55:20 .....         6656         6656  .rdata
2023-12-27 10:55:20 .....         2048         2048  .pdata
2023-12-27 10:55:20 .....         2048         2048  .xdata
2023-12-27 10:55:20 .....            0            0  .bss
2023-12-27 10:55:20 .....         2048         2048  .edata
2023-12-27 10:55:20 .....         4096         4096  .idata
2023-12-27 10:55:20 .....          512          512  .CRT
2023-12-27 10:55:20 .....          512          512  .tls
                    .....          766          744  .rsrc/1033/ICON/1.ico
                    .....           20           20  .rsrc/1033/GROUP_ICON/1
                    .....         1167         1167  .rsrc/0/MANIFEST/1
2023-12-27 10:55:20 .....          512          512  .reloc
------------------- ----- ------------ ------------  ------------------------
2023-12-27 10:55:20              45473        45451  14 files

我尝试与普通的 py2exe 下载进行比较,结果相似:

$ wget https://files.pythonhosted.org/packages/b1/07/f45b201eb8c3fea1af6a9bd9f733479aa9d009139ce2396e06db7aa778c8/py2exe-0.13.0.1-cp311-cp311-win_amd64.whl
# ...
$ mkdir py2exe_0.13.0.1
$ (cd py2exe_0.13.0.1; unzip ../py2exe-0.13.0.1-cp311-cp311-win_amd64.whl)
# ...
$ 7z l py2exe_0.13.0.1/py2exe/run-py3.11-win-amd64.exe
# ...
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-10-07 18:15:11 .....        20480        20480  .text
2023-10-07 18:15:11 .....        11264        11264  .rdata
2023-10-07 18:15:11 .....          512          512  .data
2023-10-07 18:15:11 .....         2048         2048  .pdata
                    .....          766          744  .rsrc/ICON/1.ico
                    .....           20           20  .rsrc/GROUP_ICON/1
                    .....          381          381  .rsrc/MANIFEST/1
2023-10-07 18:15:11 .....          512          512  .reloc
------------------- ----- ------------ ------------  ------------------------
2023-10-07 18:15:11              35983        35961  8 files

我想这

_memimporter
仍然是一件事,因为毕竟我的测试脚本失败了“没有名为'_memimporter'的模块”;并且该包的 Python 代码中仍然有引用:

$ grep -rI _memimporter /mingw64/lib/python3.11/site-packages/py2exe
/mingw64/lib/python3.11/site-packages/py2exe/distutils_buildexe.py:##             self.excludes.append("_memimporter") # builtin in run_*.exe and run_*.dll
/mingw64/lib/python3.11/site-packages/py2exe/hooks.py:# _memimporter can be excluded because it is built into the run-stub.
/mingw64/lib/python3.11/site-packages/py2exe/hooks.py:_memimporter

...但是,我必须问 - 这

_memimporter.pyd
仍然是一个东西吗 - 如果是,我在哪里可以找到它?

python python-3.x py2exe mingw-w64
1个回答
0
投票

对,这很痛苦......无论如何,至于问题的第一部分 -

_memimporter
显然仍然是一件事,因为最近有讨论:

至于获得

_memimporter
,这又很棘手,因为你必须从源代码构建。有一个历史版本 https://github.com/mitre/caldera-py2exe - 但由于上面最近的补丁,最好直接从主 py2exe git 存储库直接构建:

$ git clone https://github.com/py2exe/py2exe py2exe_git

现在的问题是使用哪个命令来构建 - 不幸的是,主存储库 README.md 没有指定这一点(它只是提到

pip install py2exe
)。在历史仓库中,提到了一个命令
python setup.py bdist
,但它似乎已被弃用,因为它提出了:

D:/msys64/mingw64/lib/python3.11/site-packages/setuptools/__init__.py:80: _DeprecatedInstaller: setuptools.ins
taller and fetch_build_eggs are deprecated.
!!

        ********************************************************************************
        Requirements should be satisfied by a PEP 517 installer.
        If you are using pip, you can try `pip install --use-pep517`.
        ********************************************************************************

!!
  dist.fetch_build_eggs(dist.setup_requires)

我终于在相应的MINGW-packages/mingw-w64-python-py2exe/PKGBUILD文件中找到了MINGW64包用来构建的命令。

另外,请注意,我必须安装:

pacman -S mingw-w64-x86_64-python-build
pacman -S mingw-w64-x86_64-python-wheel

然后,直接的 py2exe 源代码将无法编译,因此还必须应用 PKGBUILD 文件中提到的补丁。所以我们有:

$ cd py2exe_git
$ wget https://raw.githubusercontent.com/msys2/MINGW-packages/master/mingw-w64-python-py2exe/001-setup-fix.patch
# ...
$ wget https://raw.githubusercontent.com/msys2/MINGW-packages/master/mingw-w64-python-py2exe/002-mingw-fix.patch
# ...
$ patch -p1 -i 001-setup-fix.patch
patching file py2exe_setuptools.py
Hunk #5 succeeded at 194 with fuzz 1.
patching file setup.py
Hunk #1 succeeded at 23 (offset 2 lines).
Hunk #2 succeeded at 46 (offset 1 line).
Hunk #3 succeeded at 73 (offset 1 line).
Hunk #4 succeeded at 91 (offset 1 line).
Hunk #5 succeeded at 109 (offset 1 line).
Hunk #6 succeeded at 125 (offset 1 line).
$ patch -p1 -i 002-mingw-fix.patch
patching file py2exe/hooks.py
patching file py2exe/runtime.py
Hunk #1 succeeded at 307 (offset 5 lines).
patching file source/_memimporter.c
patching file source/python-dynload.c
patching file source/start.c

好的,我们现在可以构建了 - 仍然有弃用警告,但构建将会成功:

$ python3 -m build --wheel --skip-dependency-check --no-isolation
* Building wheel...
D:/msys64/tmp/py2exe_git/py2exe_setuptools.py:10: SetuptoolsDeprecationWarning: dep_util is Deprecated. Use fu
nctions from setuptools.modified instead.
!!

        ********************************************************************************
        Please use `setuptools.modified` instead of `setuptools.dep_util`.

        By 2024-May-21, you need to update your project and remove deprecated calls
        or your builds will no longer be supported.

        See https://github.com/pypa/setuptools/pull/4069 for details.
        ********************************************************************************

!!
  from setuptools.dep_util import newer_group
running bdist_wheel
...
adding 'py2exe-0.13.0.1.dist-info/RECORD'
removing build/bdist.mingw_x86_64/wheel
Successfully built py2exe-0.13.0.1-cp311-cp311-mingw_x86_64.whl

对 - 所以这里的技巧是,一个

_memimporter.pyd
文件没有构建,只有一个
.o
文件:

$ find . -name '_mem*'
./build/temp.mingw_x86_64-cpython-311/source/_memimporter.o
./source/_memimporter.c

如果我们检查构建日志,我们会看到这个

.o
文件直接构建到
run-py311-mingw_x86_64.exe
:

gcc -s ... build/temp.mingw_x86_64-cpython-311/source/_memimporter.o ... -lpython3.11 -o build/lib.mingw_x86_64-cpython-311/py2exe/run-py311-mingw_x86_64.exe -m64 -mconsole -municode

...这可能就是为什么无法从

_memimporter.pyd
中提取
.exe
的原因。

所以,现在我们有了

.o
文件,但我们需要
.pyd
- 我在 如何创建 .pyd 文件? 中找到了提示(值得庆幸的是,还引用了 MSYS2/MINGW64) - 所以最终,命令是:

gcc -shared -L/mingw64/bin \
./build/temp.mingw_x86_64-cpython-311/source/_memimporter.o \
build/temp.mingw_x86_64-cpython-311/source/memorymodule.o \
build/temp.mingw_x86_64-cpython-311/source/myloadlibrary.o \
build/temp.mingw_x86_64-cpython-311/source/actctx.o \
build/temp.mingw_x86_64-cpython-311/source/python-dynload.o \
-lpython3.11 -o _memimporter.pyd

所以,现在我们有一个

_memimporter.pyd
;为了使其可用以便测试脚本能够工作,我们将其复制到
/mingw64/lib/python3.11/site-packages/
(由于某种原因,将其复制到
/mingw64/lib/python3.11/site-packages/py2exe
不起作用):

$ cp -av /tmp/py2exe_git/_memimporter.pyd /mingw64/lib/python3.11/site-packages/
'/tmp/py2exe_git/_memimporter.pyd' -> '/mingw64/lib/python3.11/site-packages/_memimporter.pyd'

然后我们终于可以测试导入并没有看到错误:

$ python3 -c 'import _memimporter'
$

现在我们可以从OP运行测试脚本 - 但是,由于某种原因,我没有得到

_socket
的打印输出:

$ python3 test_zipextimporter.py
$

...但至少没有与

_memimporter
相关的错误。

© www.soinside.com 2019 - 2024. All rights reserved.