PyInstaller 使用时出现“No module named”错误

51

我试图在Windows 7上使用PyInstaller编译一个Python项目。这个项目本身运行得很好,没有问题,但是当我尝试编译它时,结果却不能正常工作。虽然在编译过程中我没有收到任何警告,但在build目录下的warnmain.txt文件中有很多警告:warnmain.txt

我实在不理解那些警告,例如“no module named numpy.pi”,因为numpy.pi不是模块而是一个数字。我从未尝试导入numpy.pi。我确实导入了numpymatplotlib。此外,我还使用了PyQt4。我认为错误可能与这些库有关。

然而,我能够成功地编译一个使用numpy的简单脚本:

import sys
from PyQt4 import QtGui, QtCore
import numpy as np

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        self.pb = QtGui.QPushButton(str(np.pi), self)

app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())

在这里成功意味着创建的可执行文件实际上显示了所需的输出。但是也创建了一个warnmain.txt文件,其中包含与之前完全相同的“警告”。因此,我想实际项目编译不成功的事实并非(或至少不仅仅)与这些警告有关。那么还可能出现什么错误呢? 编译过程中唯一的输出是“INFO”,没有任何负面声明。

我没有指定额外的挂钩目录,但是从编译输出中读取,钩子使用默认目录下的,例如,hook-matplotlib被执行。 我看不到任何numpy挂钩,也不能为我的小例子脚本找到任何挂钩,但这个脚本可以运行。 我在文件中使用了以下导入(不是所有导入都在同一个文件中,而是在不同的文件中):

import numpy as np
import matplotlib.pyplot as ppl
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
from PyQt4 import QtGui, QtCore
import json
import sys
import numpy # added this one later
import matplotlib # added this one later

由于 PyInstaller 没有给出任何错误/警告,我无法判断问题是否与库相关或是否有其他需要考虑的事项。


当您尝试从命令行启动程序时,是否出现错误?还是它根本不会启动,也没有任何输出(QT是否将stdout重定向到其他地方,例如在崩溃时关闭的输出窗口)...进一步评论,我怀疑您遇到了崩溃(可能来自使用json / xml资源或其他东西(而不是import xxxx)的某些内容),并且错误消息被打印到某个QT窗口中,在崩溃时关闭...请查看qt.App是否具有redirect = False选项或其他选项以保持stdout。 - Joran Beasley
有趣的是,如果我执行 import numpy.sinh ,会出现 ImportError: No module named sinh 的错误提示,只有当我执行 import numpy.numpy.sinh 时才会出现 ImportError: No module named numpy.sinh 的错误提示。你是否查看过 PyInstaller finding out what went wrong 来获取错误信息、详细导入信息和调试信息? - ThatOneDude
2
@JoranBeasley:我刚试图在cmd中启动exe,但没有任何结果,但是为了编译,我使用了标志-w(请参见http://pythonhosted.org/PyInstaller/#options-for-the-executable-output),它可以防止Windows为任何输入/输出启动控制台。如果我不使用`-w`编译,则无法获得图形用户界面。但是,当从解释器调用程序时,程序可以正常工作,因此我认为这不是内部错误。 @ssnobody:我知道那个链接,但对我没有任何好处。import numpy.sinh不起作用,因为sinh不是模块。 - a_guest
@JoranBeasley:我必须更正一下,似乎可以在没有-w的情况下编译并获得GUI。但是如果我这样做,我会得到一个控制台,在那里我可以看到很短的时间(远远不足以实际阅读)有东西被写在那里,但然后应用程序终止。GUI没有出现。我尝试将此stdout以某种方式传输到文件中,以便我可以实际阅读它。 - a_guest
2
@JoranBeasley 谢谢你,你的建议正是正确的方法!实际上有一些库缺失(我通过导入它们来解决了这个问题,请参见我的编辑后的问题)。如果你不打算发布答案,我会简要总结一下。谢谢! - a_guest
15个回答

37

我遇到了类似的问题,提示 no module named FileDialog。后来发现在 3.2 版本中,可以使用

pyinstaller --hidden-import FileDialog ...

而不必修改我的主要脚本。

请参阅列出隐藏的导入项文档。


哇,这很有帮助,谢谢。虽然我不得不通过在同一文件夹中创建__init__.py来将我的主脚本文件夹变成Python包。否则,根据可执行文件的运行位置,会发生奇怪的事情。从相对导入失败到无法成功导入“serial”的任何事情都可能发生。 - niCk cAMel
我不得不多次使用--hidden-import选项来修复ModuleNotFound错误,这些错误在尝试运行编译后的exe时出现。当使用nacl模块时,缺少的模块是_cffi_backendnacl - LarsH

29

Pyinstaller无法检测到二级导入。因此,如果您导入模块A,pyinstaller会看到它。但是,在A中导入的任何其他模块都不会被检测到。

您无需更改Python脚本中的任何内容。您可以直接将缺少的导入添加到spec文件中。只需更改以下行:

hiddenimports=[],

hiddenimports=["Tkinter", "FileDialog"],

21
如果你遇到了ModuleNotFoundError: No module named ...错误,并且你:
  • 在主脚本的目录之外调用PyInstaller
  • 在你的脚本中使用相对导入
那么你的可执行文件可能会出现找不到相对导入的问题。
解决方法如下:
  • 在与主脚本相同的目录中调用PyInstaller

  • OR 移除任何空的__init__.py文件(在Python 3.3+中,空的__init__.py文件是不必要的)

  • OR 使用PyInstaller的paths标志指定导入搜索路径。例如,如果你从主文件夹调用PyInstaller,而你的脚本位于subfolder中,则应该这样调用PyInstaller:

    pyinstaller --paths=subfolder subfolder/script.py.


4
谢谢你的答复,特别是--paths部分。非常感谢! - nathancy
1
你真是个救命恩人!!! - n1nsa1d00
1
删除空的 init.py 对我有用。 - Cobse

13

问题出在 Matplotlib 的一些运行时依赖项上。因此,编译是正常的,但运行程序会抛出一些错误。由于终端立即关闭,我没有意识到这一点。将 stdoutstderr 重定向到文件后,我发现我缺少了 TkinterFileDialog 这两个库。在主程序顶部添加两个 import 解决了这个问题。


1
这是我使用的重定向命令:myprogram.exe 1> errors.txt 2>&1 --- 我得到了和你一样的结果...我也缺少了Tkinter和FileDialog模块 :) 谢谢,非常感谢。 - panofish
那么问题是PyInstaller没有捕捉到二级导入吗?还是这不是一个带有setup.py的项目? - Efren
是的。如果您导入一个模块,而该模块本身又导入其他模块,则 PyInstaller 显然不会意识到这些二级导入。 - a_guest

6

我曾经遇到过同样的问题,以下解决方案对我有效:

  1. 首先删除我所使用的虚拟环境。
  2. 使用 pip 重新安装所有模块(注意:这次我没有创建任何虚拟环境)。
  3. 然后调用 pyinstaller
  4. 随后创建的 .exe 文件顺利执行,没有任何模块导入错误。

和你一样,我发现 pyinstaller 找不到我用 Poetry 安装的模块。但是,我可以使用在使用 python3 -m venv venv 创建的“venv”虚拟环境中安装的模块。 - Sean McCarthy
这个对我有用,非常感谢。 - Ankit Chawla

2
我遇到了与pyinstaller 3.0和weblib相关的问题。在主文件中导入它并没有帮助。
升级到3.1并删除所有构建文件可以解决问题。
pip install --upgrade pyinstaller

2
回复内容存在敏感词^**$plotlibrc并将默认设置更改为PyQt4,在下面的“修改”行中查看:
#### CONFIGURATION BEGINS HERE

# The default backend; one of GTK GTKAgg GTKCairo GTK3Agg GTK3Cairo
# CocoaAgg MacOSX Qt4Agg Qt5Agg TkAgg WX WXAgg Agg Cairo GDK PS PDF SVG
# Template.
# You can also deploy your own backend outside of matplotlib by
# referring to the module name (which must be in the PYTHONPATH) as
# 'module://my_backend'.

#modified 
#backend      : TkAgg
backend      : Qt4Agg


# If you are using the Qt4Agg backend, you can choose here
# to use the PyQt4 bindings or the newer PySide bindings to
# the underlying Qt4 toolkit.

#modified 
#backend.qt4 : PyQt4        # PyQt4 | PySide
backend.qt4 : PyQt4        # PyQt4 | PySide

0
我遇到了这个问题,因为我的二进制文件在一个子文件夹中,而我将顶级目录用作我的模块根目录。也就是说,我的目录结构如下:
my-project/
└── a
    ├── b
    |   └── some_library.py
    └── c
        └── my_binary.py

我通常从my-project目录中调用my_binary.py,使用python -m a.c.my_binary命令,并将a.b库导入为from a.b import some_library。当我运行pyinstaller a/c/my_binary.py之后,尝试运行my_binary时,会出现ModuleNotFound错误。

我必须使用- paths标志运行pyinstaller,并将其指向项目根目录:

$ pyinstaller -paths=. a/c/my_binary.py
...
119 INFO: Extending PYTHONPATH with paths
['/home/me/gitroot/my-project/a/c', '/home/me/gitroot/my-project']
...

将PYTHONPATH指向项目根目录后,该模块得以被包含/解析。


0
1- 升级pip
python -m pip install --upgrade pip

2- 升级pyinstaller
pip install --upgrade pyinstaller

3- 使用--hidden-import方法
pyinstaller --hidden-import ModuleName

4- 安装模块或升级模块
pip install ModuleName 

pip install --upgrade ModuleName

0
在我的情况下,我正在使用conda在一个全新的环境中。无论是conda还是pip都不知道numpy、matplotlib等等...使用conda install numpy安装它们,然后使用pyinstaller将会解决'no module named numpy'等错误。 所以我认为这是一个找到模块路径的问题?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接