我正在创建一个超薄的Python项目,它 Package 了一个本地dll,这样其他Python开发人员就可以使用这个dll的功能,而不必担心C内部的问题。这个项目可以构建到一个轮子中,它可以被pip安装,并且可以在脚本中成功使用。但是,当与pyinstaller捆绑时,dll被忽略,因此捆绑的程序崩溃。
我知道有一个解决办法,就是明确告诉pyinstaller包含dll:pyinstaller --add-binary="source/path/mylib.dll:destination/path ./main.py
。然而,这有点违背了这样一个 Package 器的目的,即向用户混淆dll的存在。我想知道是否有一种方法可以改进我的 Package 器的项目结构,以便pyinstaller可以自动找到dll。
这就是我的 Package 器项目的结构:
wrapper
|-- wrapper
| |-- __init__.py
| |-- mylib.dll
|-- pyproject.toml
字符串pyproject.toml
:
[tool.poetry]
name = "wrapper"
version = "0.1.0"
description = ""
authors = []
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
型__init__.py
:
import ctypes
import importlib.resources as res
lib = None
with res.path("wrapper", "mylib.dll") as dll_path:
lib = ctypes.CDLL(str(dll_path))
# now defining several python functions accessing lib
型
如上所述,这个项目可以通过运行poetry build
成功构建到wheel,也可以通过pip install <wheel name>
安装。在这两种情况下,dll都被识别并复制到正确的方向(例如site-packages/wrapper)。安装后,以下脚本成功运行:main.py
:
import wrapper
# calling arbitrary functions from the wrapper module
型
但是,当运行pyinstaller ./main.py
时,库mylib.dll
被忽略,捆绑的可执行文件崩溃并出现PyInstallerImportError
。
**稍后添加:**运行pyinstaller --collect-binaries wrapper .\main.py
实际上运行良好。这是一个对我的口味来说不算太差的解决方案。然而,作为一个库开发人员,我仍然更喜欢一个不需要用户设置非标准标志就能使用我的库的解决方案。所以我期待更好的想法。
1条答案
按热度按时间eqqqjvef1#
Python团队引导我使用PyInstaller hooks,这正是我所需要的。有一个非常general example演示了这些钩子的许多功能。在我的情况下,我需要以以下方式更改我的项目结构:
字符串
新添加的文件如下所示:
__init__.py
:型
hook-wrapper.py
:型
我还必须在
pyproject.toml
中添加一个额外的部分:型
现在,任何使用我的 Package 器库的脚本都可以通过运行
pyinstaller <script name>
进行绑定。