PyInstaller --onefile throws Qt error with pandas,

2019-08-03 04:31发布

问题:

Using PyInstaller with the --onefile flag, I can successfully build the following script into a .exe:

import sys
from PyQt4 import QtGui

class Example(QtGui.QMainWindow):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()

    def initUI(self):               
        self.statusBar().showMessage('Ready')
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Statusbar')    
        self.show()

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

I get the warnings below when building: (for readability I use "PYINSTALLERDIR" to replace the full path, which is "C:\Users\name\Downloads\pyinstaller-pyinstaller-v2.0-544-g337ae69\pyinstaller-pyinstaller-337ae69\".

PYINSTALLERDIR>pyinstaller.py --onefile --log-level=WARN MainWindowHello.py
1306 WARNING: library python%s%s required via ctypes not found
1468 INFO: Adding Microsoft.VC90.CRT to dependent assemblies of final executable
2957 WARNING: library python%s%s required via ctypes not found

But the outputted 14 MB .exe runs fine and displays a Qt window. However, when I try to add pandas, matplotlib or sklearn, I run into problems with Qt.

Adding either import matplotlib or import sklearn to line 3 of my script gives me these warnings when building:

PYINSTALLERDIR>python pyinstaller.py --onefile --log-level=WARN MainWindowHello.py
1371 WARNING: library python%s%s required via ctypes not found
1528 INFO: Adding Microsoft.VC90.CRT to dependent assemblies of final executable
3051 WARNING: library python%s%s required via ctypes not found
27108 INFO: Adding Microsoft.VC90.MFC to dependent assemblies of final executable
33329 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable

When I try to run the resulting .exe (44 MB for matplotlib, 87 MB for sklearn), no Qt window is displayed and I get this error message:

WARNING: file already exists but should not: C:\Users\name\AppData\Local\Temp\_MEI75002\Include\pyconfig.h
Traceback (most recent call last):
  File "<string>", line 2 in <module>
  File "PYINSTALLERDIR\PyInstaller\loader\pyi_importers.py", line 409, in load_module
ImportError: could not import module 'PySide.QtCore'

With import pandas at line 3, I get the same warnings (as well as warnings about libzmq.pyd, but I have gotten them earlier with working programs). When I try to run the 119 MB .exe, the program crashes and throws the following error:

WARNING: file already exists but should not: C:\Users\name\AppData\Local\Temp\_MEI85162\include\pyconfig.h
Sub class of QObject not inheriting QObject!? Crash will happen when using Example.

I have tried with both PyInstaller 2.0 and the dev version. All three scenarios work well when using the default --onedir instead of --onefile. Can anyone help me figure out what goes awry when using --onefile?

UPDATE: I tried building with pandas in PyInstaller 2.1 and I still get the same error when using --onefile. Again, everything works when not using --onefile.

回答1:

I was having the same issue with a script where I was importing PyQt4 as well as some modules that were importing PySide. PyInstaller worked fine with the --onedir option (the default), but I was getting ImportError: could not import module 'PySide.QtCore' when using the --onefile option.

After reading this I tried adding 'PySide' as an exclude in my spec file to force exclusive use of PyQt4 and the exe now runs fine. The modules you've listed should work fine with PyQt4 so it should hopefully solve your issue too.

Also, while it's not a huge problem, a solution to the file already exists warning is described here. Just add these lines in the spec file after a = Analysis... to remove the duplicate that causes the warning:

for d in a.datas:
    if 'pyconfig' in d[0]: 
        a.datas.remove(d)
        break