0

我无法让 PyInstaller 在一台 PC(PC-Good)上生成的 exe 在另一台(PC-Bad)上工作。

  • 该 exe 在 PC-Good 上创建,并在 PC-Good 上按预期执行
  • 两台电脑都运行 Windows 10
  • 调用大多数 matplotlib.pyplot 方法(例如 subplots() 或 plot())时,PC-Bad 出现问题
  • 即使 matplotlib 处于非交互模式,问题仍然存在
  • 失败时不报告错误。exe简单地退出
    • 即使 matplotlib 详细程度更改为“调试”
    • 即使在 try-exception 中捕获了问题陈述

请参阅下面的代码:

print('Start')
import matplotlib
matplotlib.use('Agg')

import matplotlib.pyplot as plt
print("Import of matplotlib & pyplot successful")

plt.set_loglevel("debug")

x = [0, 1, 2, 3, 4]
y = [4, 3, 2, 1, 0]
print('list creation successful')

try:
    fig, ax = plt.subplots(1, 1, figsize=(12, 6))
except Exception as exception:
    print(exception.__class__.__name__ + ": ", + exception.message)
finally:
    print('run subplots() successful')

plt.scatter(x, y)
print('plot creation successful')
plt.savefig('saved_plot.png')
print('code complete')

PC-Good 上的输出:

Start
C:\tools\miniconda3\envs\bcht\lib\site-packages\PyInstaller\loader\pyimod03_importers.py:623: MatplotlibDeprecationWarning:
The MATPLOTLIBDATA environment variable was deprecated in Matplotlib 3.1 and will be removed in 3.3.
  exec(bytecode, module.__dict__)
Import of matplotlib & pyplot successful
list creation successful
run subplots() successful
plot creation successful
DEBUG:matplotlib.font_manager:findfont: ...
(and many more matplotlib DEBUG messages)
code complete

PC-Bad 上的输出:

Start
C:\tools\miniconda3\envs\bcht\lib\site-packages\PyInstaller\loader\pyimod03_importers.py:623: MatplotlibDeprecationWarning:
The MATPLOTLIBDATA environment variable was deprecated in Matplotlib 3.1 and will be removed in 3.3.
Import of matplotlib & pyplot successful
list creation successful

因为我没有得到错误输出,所以我很不知道下一步该去哪里。Matplotlib 文档没有提供任何关于获取更精细的调试消息的提示,例如绘图或子图。有没有其他人观察到这样的问题或知道修复?或者有谁知道是否有办法让 Matplotlib 告诉我更多信息?

4

2 回答 2

0

这可能有多种原因。

  1. Pyinstaller 没有“完全”包含模块:pyinstaller 尝试通过仅包含应用程序使用的模块部分来减小大小。它可能没有检测到模块的某些重要部分的使用并且没有包含它。尝试在一种目录模式下使用 pyinstaller。然后您将能够看到 pynstaller 选择的模块。如果缺少某些内容,那么下次您可以指定包含该模块。

  2. 尝试print("reached some function")在代码中放置检查点以进行调试。它将更容易找到问题所在。

  3. 还尝试在目标计算机上的普通 python 中运行代码。

于 2021-01-27T03:20:17.593 回答
0

我找到了解决此问题的方法,但由于 PyInstaller 和 MatPlotlib 都没有提供任何调试消息来进一步调查根本原因,因此我还不能称之为修复。尽管如此,它摆脱了我看到的问题。

TL;博士

  • 问题是由于使用 PyInstaller 生成带有 matplotlib 3.1.3 和 numpy 1.18.1 的 Python 代码的可执行文件时不兼容。这种不兼容不会导致 python 脚本本身出错。这种不兼容性不会产生任何指向自身的错误消息或症状,因此很难找到根本原因。
  • 如果有人观察到冻结的可执行文件静默退出而没有任何错误消息。值得调查这是否是由于库不兼容造成的。如果在执行 mpl 方法期间发生退出,则立即查看 numpy。

现在是 TL: 一开始怀疑问题是由于虚拟环境或 conda 干预了冻结过程(它们不是),所以我使用另一台计算机安装了干净的 python(3.7.9)和 matplotlib 3.1.3它自动填充其所有依赖项(让我们将此新环境称为“精益环境”,并将问题陈述中的源 PC 称为“完整环境”)。我在精益环境中复制了捆绑/冻结过程,一切正常。在这一点上,我注意到精益环境中的许多库比完整环境中的新。所以我在完整的环境中升级了它们,包括:

numpy 从 1.18.1 到 1.20.0 kiwisolver 从 1.3.0 到 1.3.1

在此之后,完整的 env 还能够生成一个在源 PC 和目标 PC 上运行时都可以正常工作的包。所以问题很可能是 matplotlib 3.1.3 和这两者之一之间的“沉默”不兼容。

为了进一步缩小范围,我在完整环境中将 numpy 恢复为 1.18.1 并重现了我看到的旧问题。它在那里。

令人沮丧的是,numpy 和 matplotlib 都没有产生任何可识别的错误(Pyinstaller 也没有)。此外,matplotlib 本身没有任何方法可以生成任何有用的详细调试消息来进一步调查。(我确实打开了matplotlib的log_level进行调试,但只得到了一些指示正在使用的字体的信息。)出于这个原因,我不会进一步调查。解决方法足以满足我的使用需求。如果其他人有兴趣,请随时询问 mpl。我也不会在 pyinstaller、matplotlib 和 numpy 之间进行进一步的互操作。我要说的是:

好:matplotlib==3.1.3,numpy==1.20.0,pyinstaller==3.6

不好:matplotlib==3.1.3,numpy==1.18.1,pyinstaller==3.6

于 2021-02-01T22:35:23.343 回答