ModuleNotFound异常与zipapp和编译的C代码



我在使用Python的zipapp功能时遇到了奇怪的行为。

Python版本:3.10.5

# these steps come from the docs: https://docs.python.org/3/library/zipapp.html
$ mkdir myapp
# this is the library I'd like to use
$ echo "cysystemd==1.5.3" > requirements.txt
$ pip install -r requirements.txt --target myapp
# prepare the zipapp entry point, just import the library
$ echo "from cysystemd import journal" > myapp/__main__.py
# executing the directory works fine. the import takes place and the program terminates successfully.
$ python3 myapp/
# zipapping
$ python -m zipapp -p "python3" myapp 
# now executing again, this time the zipapp:
$ ./myapp.pyz                                                                               
Traceback (most recent call last):
File "/home/samba/.pyenv/versions/3.10.5/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/home/samba/.pyenv/versions/3.10.5/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/samba/git_wsl/zipapp_experiment/./myapp.pyz/__main__.py", line 1, in <module>
File "/home/samba/git_wsl/zipapp_experiment/./myapp.pyz/cysystemd/journal.py", line 7, in <module>
ModuleNotFoundError: No module named 'cysystemd._journal'

我无法理解这个导入问题。_journal指的是一个编译后的C模块,它存在于两个位置,myapp目录和zipappmyapp.pyz:

$ find myapp/ | grep journal                                                              
myapp/cysystemd/journal.py
myapp/cysystemd/__pycache__/journal.cpython-310.pyc
myapp/cysystemd/_journal.cpython-310-x86_64-linux-gnu.so
$ unzip -l myapp.pyz| grep journal                                                    
4880  2022-06-21 21:39   cysystemd/journal.py
301104  2022-07-19 18:47   cysystemd/_journal.cpython-310-x86_64-linux-gnu.so
5043  2022-07-19 18:47   cysystemd/__pycache__/journal.cpython-310.pyc

你知道这是怎么回事吗?我怀疑与sys.path有关的问题,但我不知道如何在zipapp存档中修复此问题。

这是Python的导入机制所施加的限制。Python有各种导入钩子:

>>> import sys
>>> sys.path_hooks
[zipimport.zipimporter,
<function _frozen_importlib_external.FileFinder.path_hook...]

zipimport说:

任何文件都可能存在于ZIP存档中,但是只有.py和.pyc文件才会调用导入器。动态模块的ZIP导入。pyd, .so)是不允许的.

为了绕过这个限制,该空间中的工具(如pex, shiv,…)使用zipapp方法,但它们会在运行zip文件之前透明地提取zip文件-因此绕过了zipimport模块的限制。

请看看使用cysystemd与shiv工具在这里:

  • https://gist.github.com/miku/e0a3d4abb2ba7dbb9ca5f11369fc64f4

p。有相当多的包装选择;Python包装管理局对此有更多信息;一些关于主题的演讲:"包装梯度",PyBay2017,"包装Python应用",PyCon巴尔干2018,…

相关内容

  • 没有找到相关文章

最新更新