问题

最近在项目里用到了pikepdf这个库,用于实现pdf水印插入的一个小功能,源码调试阶段运行一切OK但是在出包时报了如下异常。

Traceback (most recent call last):
File "pikepdf\__init__.py", line 19, in <module>
File "PyInstaller\loader\pyimod03_importers.py", line 495, in exec_module
File "pikepdf\_version.py", line 13, in <module>
File "importlib\metadata.py", line 530, in version
File "importlib\metadata.py", line 503, in distribution
File "importlib\metadata.py", line 177, in from_name
importlib.metadata.PackageNotFoundError: pikepdf The above exception was the direct cause of the following exception: Traceback (most recent call last):
File "main.py", line 1, in <module>
File "PyInstaller\loader\pyimod03_importers.py", line 495, in exec_module
File "pikepdf\__init__.py", line 21, in <module>
ImportError: Failed to determine version
[29708] Failed to execute script 'main' due to unhandled exception!

异常定位

打印了两份堆栈的信息,翻翻炸出来点 init.py 的21行,代码如下

try:
from ._version import __version__
except ImportError as _e: # pragma: no cover
raise ImportError("Failed to determine version") from _e

从.version.py文件导入__version__失败?看看_version.py

try:
from importlib_metadata import version as _package_version # type: ignore
except ImportError:
from importlib.metadata import version as _package_version __version__ = _package_version('pikepdf') __all__ = ['__version__']

再看看上面的异常,也就再_package_version这个函数了。这边可以先写个简单的demo.py验证下,使用pyinstgaller编译后运行。

# demo.py
import pikepdf if __name__ == '__main__':
print("Hello World")
# 输出
Traceback (most recent call last):
File "pikepdf\__init__.py", line 19, in <module>
File "PyInstaller\loader\pyimod03_importers.py", line 495, in exec_module
File "pikepdf\_version.py", line 13, in <module>
File "importlib\metadata.py", line 530, in version
File "importlib\metadata.py", line 503, in distribution
File "importlib\metadata.py", line 177, in from_name
importlib.metadata.PackageNotFoundError: pikepdf The above exception was the direct cause of the following exception: Traceback (most recent call last):
File "main.py", line 1, in <module>
File "PyInstaller\loader\pyimod03_importers.py", line 495, in exec_module
File "pikepdf\__init__.py", line 21, in <module>
ImportError: Failed to determine version
[29708] Failed to execute script 'main' due to unhandled exception!

符合预期。所以说importlib.metadata.version 无法在pyinstaller打包后运行?

问题原因

对于pkgs_to_check_at_runtime中列出的每个包,需要通过在spec文件中使用copy_metadata(name)来收集元数据。说白了就是pyinstaller打包后缺少对应的metadata信息。

修复方案

1. 降低版本pikepdf的版本

这个库以前用过,没有出这个幺蛾子。看了下旧版本的源代码,一下是5.1.3版本之前的get_version实现,没有使用importlib库,自然也不会有问题。

from pkg_resources import DistributionNotFound
from pkg_resources import get_distribution as _get_distribution try:
__version__ = _get_distribution(__package__).version
except DistributionNotFound: # pragma: no cover
__version__ = "Not installed" __all__ = ['__version__']

2. 在pyinstaller打包时指定copy-metadata

像这样

pyinstaller -F --copy-metadata pikepdf main.py

碎碎念

我觉得完全可以像版本5.1.3之前一样,获取不到时赋值为"Not installed"一样就行。然后提了个pr[https://github.com/pikepdf/pikepdf/pull/358]给作者,可惜作者认为这是importlib的锅(不改),倒也时说得过去。

Pyinstaller打包pikepdf失败的问题排查的更多相关文章

  1. pyinstaller打包exe运行失败

    使用Pyinstaller来打包自己开发的软件时遇到的几个问题及解决方法.工具主要功能是数据分析,使用机器学习算法完成数据训练和预测功能.主要用到了两个学习库keras和sklearn,所以说在打包时 ...

  2. [python学习笔记] pyinstaller打包pyqt5程序无法运行

    问题 pyinstaller打包的pyqt5程序在部分电脑上会失败.用户截图提示下边错误日志 无法定位程序输入点 ucrtbase.terminate 于动态链接库 api-ms-win-crt-ru ...

  3. pyinstaller 打包生成exe之后运行提示‘no module name 'xxx'’错误

    python 3.7 pyinstaller 3.4 具体情况: pycharm中点击运行可成功执行,生成正确结果,没有报错. 双击run.py(程序运行的主文件),运行,可生成正确结果,没有报错. ...

  4. pyinstaller 打包exe可执行文件

    Python打包EXE方法之一 一.安装Pyinstaller 1.安装pywin32 下载安装文件:查找到跟自己适用的python版本及window系统版本匹配的pywin32,下载后安装 使用pi ...

  5. 【爬坑】python3+pyqt5+pyinstaller 打包成exe的各种问题

    windows系统+python3+pyqt5+pyinstaller打包,经常会出现各种打包异常情况.如果代码没有特别异常,那么综合原因,大抵都是这四个元素之间的匹配问题,引起的.作者:一心狮链接: ...

  6. Python: pyinstaller打包exe(含file version信息)

    最近项目上一直都是用Spyder直接运行.py文件的方式来执行每日的自动化程序,每天都要手动去点击Run来执行一次,所以考虑把.py文件直接打包成exe,然后用windows的task schedul ...

  7. python用pyinstaller打包成exe文件

    版本为Python2.7 一.安装Pyinstaller 1.安装pywin32 下载安装文件:查找到跟自己适用的python版本及window系统版本匹配的pywin32,下载后安装  使用pip命 ...

  8. pyinstaller 打包exe程序读不到配置文件No such file

    挺久没更新博客的,一来之前是觉得才疏学浅,记录下来的太简单没人看.二来时间上不是很充裕(不是借口,有时间打游戏,没时间总结) 偶然有一次发现同事在搜索解决问题的时候正在看我博客的解决思路,很奇妙的感觉 ...

  9. pyinstaller打包python文件成exe(原理.安装.问题)

    py文件打包成exe文件的方式一共有三种:py2exe.PyInstaller和cx_Freeze 本文分四个步骤来详讲如何用PyInstaller将py文件打包成exe文件 1. PyInstall ...

随机推荐

  1. 『现学现忘』Git基础 — 5、Git的协作模式

    目录 1.分布式工作流程 2.集中式工作流 3.分支工作流 4.GitFlow 工作流(最流行) 5.Forking 工作流(偶尔使用) 6.总结 1.分布式工作流程 与传统的集中式版本控制系统(CV ...

  2. JavaScript学习③

    3. 属性: PI 6. Number 7. String 8. RegExp:正则表达式对象 1. 正则表达式:定义字符串的组成规则. 1. 单个字符:[] 如: [a] [ab] [a-zA-Z0 ...

  3. Junit单元测试:

    * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具体的执行流程. * Junit使用:白盒测试 * 步骤: 1. 定义一个测 ...

  4. ArcGIS使用技巧(三)——关于投影

    新手,若有错误还请指正! 简单记录一下自己所理解的ArcGIS中的有关投影的知识点. 在数据处理过程中,基本都是需要将相关数据放在同一投影坐标系下,需要用到投影转换工具,但若有的数据没有坐标信息,则首 ...

  5. 2021.11.04 P1392 取数(多路归并)

    2021.11.04 P1392 取数(多路归并) P1392 取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 在一个n行m列的数阵中,你须在每一行取一个数(共n个数) ...

  6. async异步函数的执行顺序

    1 async function async1(){ 2 console.log('async1 start') //2 3 await async2() 4 //await async2()后面的内 ...

  7. Es5 - 11 详解

    一.ES简介 ECMAScript,欧洲计算机制造商协会 ES是一种标准,而JS是ES的一种实现 每年的ES版本中都会引入新特性 二.NRM的安装与使用 NRM是切换源的工具 ES6 2.1安装 wi ...

  8. Mysql基本操作语句 增-删-改-查

    增 INSERT INTO 表名(属性名1,属性名2) VALUES(值1,值2) 删 DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子 ...

  9. py文件加密打包成exe文件

    python的py.pyc.pyo.pyd文件区别 py是源文件: pyc是源文件编译后的文件: pyo是源文件优化编译后的文件: pyd是其他语言写的python库: 为什么选用Cpython .p ...

  10. 【mq】从零开始实现 mq-04-启动检测与实现优化

    前景回顾 [mq]从零开始实现 mq-01-生产者.消费者启动 [mq]从零开始实现 mq-02-如何实现生产者调用消费者? [mq]从零开始实现 mq-03-引入 broker 中间人 [mq]从零 ...