简体   繁体   中英

exe built with cx_Freeze, PyQt5, Python3 can't import ExtensionLoader_PyQt5_QtWidgets.py and run

I'm trying to pack my app Python3, PyQt5 for Windows using cx_Freeze. I've installed Python 3.4.3, Python-win32, PyQT5, cxfreeze. Application itself, run in console, works fine.

I try to pack it with cx_freeze: python setup.py build_exe. It works on the same host. But when I move it to another clean installation WinXP it gives an error:

Traceback:
File "C:\Python34\lib\site-packages\cx_Freeze\initscripts\Console.py", line 27 in <module>
File "pyftp1.py" in 7, in <module>
File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", in 2237, in _find_and_load
File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", in 2226, in _find_and_load_unlocked
File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", in 1191, in _load_unlocked
File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", in 1161, in _load_backward_compatible
File "ExtensionLoader_PyQt5_QtWidgets.py", line 22, in <module>
File "ExtensionLoader_PyQt5_QtWidgets.py", line 14, in __bootstrap__ 
ImportError: DLL load failed: Не найден указанный модуль.

English: "specified module was not found".

Here's my setup.py:

import sys
from cx_Freeze import setup, Executable

includes = ['sys', 'PyQt5', 'PyQt5.Core', 'PyQt5.QtGui', 'PyQt5.QtWidgets', 'os', 'os.path', 'ftplib',
    'traceback', 'time',]
excludes = []
packages = ['os', 'PyQt5']
path = []
build_exe_options = {
   'includes': includes,
   'excludes': excludes,
   'packages': packages,
   'path'    : path,
   #'dll_includes': ['msvcr100.dll'],
   'include_msvcr' : True,
   'include_files': [
       (r'C:\Windows\System32\msvcr100.dll', 'msvcr100.dll'),
   ],

}


base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

setup(
    name = "pyftp1",
    version = "0.1",
    description = "Foto uploader",
    options = {'build_exe_options': build_exe_options},
    executables = [Executable("pyftp1.py", base=base, appendScriptToLibrary=False, copyDependentFiles=True)]
)

Also I found it doesn't copy msvcr100.dll file, however I've stated it twice! I've copied it manually to target host.

Here's pyftp1.py:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys, time, os, hashlib
import ftplib
import traceback
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog  # <-- Line 7
from PyQt5.QtWidgets import QPushButton, QHBoxLayout, QVBoxLayout, QScrollArea, QLineEdit, QCheckBox
from PyQt5 import QtGui
from PyQt5.QtGui import QIcon, QPalette, QLinearGradient, QColor, QBrush
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot

Solution.

After struggling during a lot of time with a problem I've found the solution. Many how-to do not take an account specific versions of software, or some specific modules used, or even they do not check .exe on fresh system, which has no your libraries dlls and so on. Here's working and tested solution.

First, I removed cx_freeze and used py2exe. I've built all the stuff on WinXP 32-bit - for the goal it could be run on nearly every system. You need:

  • Win XP 32-bit (or another system which you consider as minimal requirements)
  • Python 3.4 -- install from www.python.ord/download Windows x86 msi installer
  • PyWin32 -- install from sf.net pywin32-219.win32.py3.4.exe
  • Qt5.5 -- install it from qt.io, also you get mingw, next add folder C:\\Qt\\Tools\\mingw492_32\\bin to your system env %PATH%.
  • Git for Windows -- install from git-scm.com
  • PyQt5 -- download from riverbankcomputing.co.uk win32 x86 installer and run it
  • SIP -- the worst intallation!
    • Download it from riverbankcomputing.co.uk,
    • unzip,
    • run Git Bash,
    • python configure.py -p win32-g++ ,
    • mingw32-make.exe install.
    • It fails (. You go manually to sipgen/ folder and copy sip.exe to c:\\Python34. Next go to ../siplib and copy sip.pyd to c:\\python34\\Lib\\site-packages, then
    • strip /c/Python34/Lib/site-packages/sip.pyd
    • cp sip.h /c/Python34/include/
  • py2exe -- python -m pip install py2exe
  • 7-Zip -- install from 7-zip.org as x86 exe
  • 7-zip extra, unpack into installed 7-zip folder, conflicts with .txt files could be ignored
  • Resource Hacker -- from angusj.com -- however it's not necessary if you don't want to set to patch your .exe finally and give it a nice icon

Next I added setup.py to the project:

from distutils.core import setup
import os, sys
import py2exe
from glob import glob
import PyQt5

NAME="ProgName"

qt_platform_plugins = [("platforms", glob(PyQt5.__path__[0] + r'\plugins\platforms\*.*'))]
data_files.extend(qt_platform_plugins)
msvc_dlls = [('.', glob(r'C:\Windows\System32\msvc?100.dll'))]
data_files.extend(msvc_dlls)
# print(data_files)

sys.argv.append('py2exe')

setup(
    data_files=data_files,
    # windows=["pyftp1.py",],
    windows=[
        {
            "script": "pyftp1.py",
            "icon_resources": [(0, "resources/favicon.ico")]
        }
    ],
    # zipfile=None,
    options={
        "py2exe": {
            "includes":["sip", "atexit",],
            # "packages": ['PyQt5'],
            "compressed": True,
            "dist_dir": "dist/" + NAME,
            # "bundle_files": 0,
            # "zipfile": None,
            "optimize": 2,
        }
    }
)

Just not to run all the actions manually, you may add Makefile

# start settings
DIST=dist
# change NAME also in setup.py and resource/config.txt
NAME=ProgName
EXT=exe

# final name and location of the built program
FINAL=$(DIST)/$(NAME).$(EXT)

# external programs
7ZIPDIR="C:\Program Files\7-Zip"
RESHACKER="/c/Program\ Files/Resource\ Hacker/ResourceHacker.exe"

# intermediate steps

# no icon version of program 
NOICON=$(DIST)/$(NAME)_no_icon.$(EXT)

# name of .7z archive
7Z_BASENAME=$(NAME).7z
7Z=$(DIST)/$(7Z_BASENAME)

# folder with ready .exe
PROGDIR=$(DIST)/$(NAME)

all: $(FINAL)


$(FINAL): $(NOICON)
    # change icon
    "$(RESHACKER)" -addoverwrite $(NOICON), $(FINAL), resources/favicon.ico, ICONGROUP, MAINICON, 0


$(NOICON): $(7Z)
    #build autorunning sfx with default icon
    cat $(7ZIPDIR)/7zS.sfx resources/config.txt $(7Z) > $(NOICON)


$(7Z): exe
    # compress program folder to .7z
    cd $(DIST);  $(7ZIPDIR)\\\7z.exe a  $(7Z_BASENAME)  $(NAME)


exe:  $(DIST)
    # build program itself
    python setup.py py2exe


$(DIST):
    # create dist directory
    # echo $(DIST)/


clean:
    rm -rf $(DIST)/*

Now you can easily build your program itself - as a folder of files: mingw32-make.exe exe Or make a single file with correct icon: mingw32-make.exe all Or clean that all stuff: mingw32-make.exe clean

you could try this:

  1. add 'libEGL.dll' to your working folder. This is from Python3x\\Lib\\site-packages\\PyQt5

  2. In cx-freeze setup.py add:

    if sys.platform == "win32": includefiles = ['libEGL.dll'] #here you should add other files if you need to

  3. In cx-freeze setup.py link "includefiles" to build_exe_options like this:

    build_exe_options= { ... ... 'include_files': includefiles, }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM