Issue/question with PyQT / resources / cx_freeze on Windows:
I'm using QT's resource system to set an application icon. (Goes in the top left corner of the Window for Windows programs) I created the resource in Designer, then used pyrcc4 to create a rc.py file. It works properly on my uncompiled program, but fails to show (Shows the generic windows program icon instead) when compiling the script with cx_freeze. Note that I am not referring to the icon you click to launch the program - that's not handled by QT, and works properly. Any ideas? This is my setup.py.
from sys import platform
from cx_Freeze import setup, Executable
import module_locator
_dir = module_locator.module_path()
base = None
if platform == "win32":
base = "Win32GUI"
setup(
name = "Plates",
version = "0.1",
description = "Downloads approach plates",
executables = [Executable(_dir + '\\plates.pyw',
base = base, icon = _dir + '\\icon.ico')],
)
I get no errors when building the program. My rc file does exist (as a compiled python file) in library.zip.
Reposting as an answer:
Qt needs plugins to display some image formats. Look for a folder called 'imageformats' and copy it into your application directory (next to the exe).
The next version of cx_Freeze should find and copy imageformats automatically when you use QtGui.
Related
I'm trying to build a simple app on OSX using cx_Freeze. The build using setup.py seems to go fine - it builds a .dmg and .app for my application, along with all of the source files. However, when I try to run the .app, it crashes immediately, saying "My_App quit unexpectedly". Frustratingly, I don't see any decipherable error codes I can track down.
I have stripped down the app into a very simple example. Below are my main python file and my setup file.
my_app.py
from tkinter import *
root = Tk()
root.title("Welcome to My_App")
root.geometry('350x200')
root.mainloop()
setup.py
import sys
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": [], "excludes": []}
# base="Win32GUI" should be used only for Windows GUI app
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(
name = "My_GUI",
version = "1.0",
description = "My GUI application!",
options = {"build_exe": build_exe_options},
executables = [Executable("my_app.py", base=base)]
)
I have built an .exe on windows before, and when startup fails on windows, I at least get a traceback error message that I can track down. On OSX, it doesn't appear to do the same thing.
What's going wrong? How can I get more information on why my app is failing to start up? Below are images of my build and the error I'm getting on startup.
Ok turns out if I run the file from terminal, it outputs an actual error code. From there, I was able to track down that I did not have zlib installed. I was getting error
zipimport.ZipImportError: can't decompress data; zlib not available
What ultimately solved it for me was reading through this thread
https://github.com/jiansoung/issues-list/issues/13
I'm attempting to package a PyQt application using cx_freeze. I'm running Python 3.4, Qt 5.6, PyQt 5.5.1 and Cx_freeze 4.3.4 on Windows 7.
There are three pieces to my application, the python/PyQt code, a Qt UI file which contains the GUI elements, and a QML file which runs an interactive map similar to the places_map.qml example. The QML file using the osm map plugin.
My Qt UI file includes a QQuickWidget whose source is the QML file. I'm attempting to package the application, so that others can run it without installing python and Qt. I've created a custom setup.py scripts for cx_freeze to use. However, I keep encountering various ImportErrors related to the QQuickWidget when running my built Exe files. The error occurs when my Python code loads the UI file. I've attempted to include pretty much anything related to QQuickWidgets and the QML code that I can think of in my setup.py file. Initially, the ImportError was missing QQuickWidgets. After adding the SIP QQuickWidget files, the error is now related to QQuickWidgets.QQuickWidget. Below is my setup.py file.
from cx_Freeze import setup, Executable
import os
PYQT5_DIR = "c:/Python34/lib/site-packages/PyQt5/"
include_files = ['TTRMS.ui','places_map.qml',
(os.path.join(PYQT5_DIR, "qml", "QtQuick.2"), "QtQuick.2"),
(os.path.join(PYQT5_DIR, "qml", "QtQuick"), "QtQuick"),
(os.path.join(PYQT5_DIR, "qml", "QtQml"), "QtQml"),
(os.path.join(PYQT5_DIR, "qml", "Qt"), "Qt"),
(os.path.join(PYQT5_DIR, "qml", "QtPositioning"), "QtPositioning"),
(os.path.join(PYQT5_DIR, "qml", "QtLocation"), "QtLocation"),'C:/Python34/Lib/site-packages/PyQt5/uic/widget-plugins',
'C:/Python34/Lib/site-packages/PyQt5/plugins/geoservices','C:/Python34/Lib/site-packages/PyQt5/sip/PyQt5/QtQuickWidgets',
'C:/Python34/Lib/site-packages/PyQt5/sip/PyQt5/QtQuick']
buildOptions = dict(packages = ['PyQt5.QtQuickWidgets',"atexit","sip","PyQt5.QtCore","PyQt5.QtGui","PyQt5.QtWidgets",
"PyQt5.QtNetwork","PyQt5.QtOpenGL", "PyQt5.QtQml", "PyQt5.QtQuick"],
excludes = [], includes = ["atexit","re"], include_files = include_files)
import sys
base = 'Win32GUI' if sys.platform=='win32' else None
executables = [
Executable('Main.py', base=base, targetName = 'main.exe')
]
setup(name='TTRMS',
version = '1.0',
description = 'Travel Time Reliability',
options = dict(build_exe = buildOptions),
executables = executables)
Here is the error when running my Exe:
I'm not sure what else I need to include in my setup.py in order to package the application properly. I've successfully packaged a small PyQt app with a UI file, but never a UI file which then imports QML through a QQuickWidget. I'm not very knowledgeable about Qt either, so this whole process is new to me. Please let me know if you have any suggestions and let me know if I need to clarify anything. I appreciate any help!
My application looks different after I freeze it using cx_freeze (I'm using Gui2Exe to create and run the cx_freeze script) and when I run it using the python interpreter.
[As I'm not allowed to post images, here are the links to the UI, edit?]
Script run:
Application as run from the command line
Frozen run:
Application as run after being frozen by cx_freeze
I have tried both including and not including the manifest file in the cx_freeze script, yet I'm unsure what could be causing the application UI to change so dramatically.
Here is the cx_freeze script:
# ======================================================== #
# File automagically generated by GUI2Exe version 0.5.3
# Copyright: (c) 2007-2012 Andrea Gavana
# ======================================================== #
# Let's start with some default (for me) imports...
from cx_Freeze import setup, Executable
# Process the includes, excludes and packages first
includes = ['ast', 'gobject', 'gtk']
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
'Tkconstants', 'Tkinter']
packages = ['BeautifulSoup', 'mechanize', 'pygtk']
path = []
# This is a place where the user custom code may go. You can do almost
# whatever you want, even modify the data_files, includes and friends
# here as long as they have the same variable name that the setup call
# below is expecting.
# No custom code added
# The setup for cx_Freeze is different from py2exe. Here I am going to
# use the Python class Executable from cx_Freeze
GUI2Exe_Target_1 = Executable(
# what to build
script = "moodle-downloader.py",
initScript = None,
base = 'Win32GUI',
targetDir = r"md",
targetName = "moodle-downloader.exe",
compress = True,
copyDependentFiles = True,
appendScriptToExe = True,
appendScriptToLibrary = True,
icon = r"C:\Users\Nasser.Al-Hilal\Dropbox\CodeN\Projects\Applications\Personal\MoodleDownloader\res\md.ico"
)
# That's serious now: we have all (or almost all) the options cx_Freeze
# supports. I put them all even if some of them are usually defaulted
# and not used. Some of them I didn't even know about.
setup(
version = "0.3",
description = "An app to assist in downloading assignment submissions from Moodle LMS.",
author = "Nasser Al-Hilal",
name = "Moodle Downloader",
options = {"build_exe": {"includes": includes,
"excludes": excludes,
"packages": packages,
"path": path
}
},
executables = [GUI2Exe_Target_1]
)
# This is a place where any post-compile code may go.
# You can add as much code as you want, which can be used, for example,
# to clean up your folders or to do some particular post-compilation
# actions.
# No post-compilation code added
# And we are done. That's a setup script :-D
I would prefer if I can get the application to look the same as when run from the interpreter.
For you to work you have to download gtkruntime, install it on your system, then copy the lib folder and share your generated build folder, then copies the contents of the bin folder gtkruntime your build folder, and then you work.
My installation:
windows 7
Python 2.7.9
GTK2 (python -m pip install pygtk)
pycairo (1.8.10) pygobject (2.28.3)
pygoocanvas (0.14.2)
pygtk (2.24.0)
pygtksourceview (2.10.1)
cx-Freeze (python -m pip install cx-Freeze)
cx-Freeze (4.3.4)
cx-freeze compile command:
\Py279\Scripts\cxfreeze MyGUIapp.py --target-dir somewheredir --base-name=Win32GUI
(in essence, all done without any setup command files, although some can be created :) )
once cx-freeze compiles to exe and copy dll it believes that are needed I get motif/x11 look/feel however, when I add to somewheredir all .dll files from:
\Py279\Lib\site-packages\gtk-2.0\runtime\lib\gtk-2.0\2.10.0\engines\
to:
somewheredir\lib\gtk-2.0\2.10.0\engines\
I get windows look and feel.
Files found there in my case are:
libpixmap.dll
libsvg.dll
libwimp.dll
that's all.
Plus:
some further design customization influence can be achieved by creating .gtkrc-2.0 in the user's home folder c:\Users\myuser. Namely one can influence default font face and size used, window background color and such. For example, following code (hints from elsewhere)
style "win32-font" {
# make default font larger
font_name = "Sans 12"
# set the background to a light grey
bg[NORMAL] = "#f6f6f6"
}
class "*" style "win32-font"
placed in c:\Users\myuser\.gtkrc-2.0 would change 'default' font size and change top window background for pygtk applications run by user (meaning each user can set its own preferences there).
This is just a translation of Blasito's answer:
"For this to work correctly, first download and install GTK-runtime on your computer. Then navigate to GTK-runtime installation folder (in Program Files) and copy over the lib and share folders over to the generated build folder. Finally, copy the contents of the bin folder (in the installation directory) into the build folder."
I can verify this works.
I have a PySide app which has an icon for the MainWindow (a QMainWindow instance). When I run the file normally, the icon is visible and everything is fine but when I create an exe with py2exe, the icon does not appear. This happens with cx_freeze also( so I don't think the problem's with py2exe).
The app was designed using QtDesigner and converted to python with pyside-uic. I tried both using icons as a file and as a resource(qrc file) and both don't seem to work.
Any help or pointers would be appreciated.
Thanks.
kochelmonster's solution works so long as you don't try and bundle the Qt dlls into library.zip or the exe. You also don't need to set a library path if you put the plugins in the base of the app directory.
I still wanted to bundle everything else so I excluded the qt dlls and added them manually. My setup.py looks something like this:
from os.path import join
_PYSIDEDIR = r'C:\Python27\Lib\site-packages\PySide'
data_files =[('imageformats',[join(_PYSIDEDIR,'plugins\imageformats\qico4.dll')]),
('.',[join(_PYSIDEDIR,'shiboken-python2.7.dll'),
join(_PYSIDEDIR,'QtCore4.dll'),
join(_PYSIDEDIR,'QtGui4.dll')])
]
setup(
data_files=data_files,
options={
"py2exe":{
"dll_excludes":['shiboken-python2.7.dll','QtCore4.dll','QtGui4.dll'],
"bundle_files": 2
...
}
}
...
)
If your project uses additional Qt dlls you will have to exclude and manually add them as well. If you need to load something other than an .ico image you'll also need to add the correct plugin.
I'm assuming it works with a bmp, but not a png/jpg? If so, it's likely that the image format plugins don't load properly.
I'd guess setting up a qt.conf file in the installed application's directory and making sure plugin-dll's go to /plugins/imageformats/ will make things work better.
I had the same problem. After some investigation I found a solution:
(Macke had the right idea)
cx_freeze does not copy the PyQt plugins directory, which contains the ico image reader.
Here are the steps:
in setup.py copy the PyQt4 plugins directory to your distribution
In your code write something like:
application_path = os.path.split(os.path.abspath(sys.argv[0]))[0]
try:
if sys.frozen:
plugin_path = os.path.join(application_path, "qtplugins")
app.addLibraryPath(plugin_path)
except AttributeError:
pass
Could it be related to Windows 7's taskbar icon handling?
See How to set application's taskbar icon in Windows 7 for an answer to that.
You must include "qico4.dll" manually in your release folder. Insert this in your setup.py:
import sys
from os.path import join, dirname
from cx_Freeze import setup, Executable
_ICO_DLL = join(dirname(sys.executable),
'Lib', 'site-packages',
'PySide', 'plugins',
'imageformats', 'qico4.dll')
build_exe = {
'include_files': [(
_ICO_DLL,
join('imageformats', 'qico4.dll'))]}
setup(name = "xxxxx",
version = "1.0.0",
...
options = { ...
'build_exe': build_exe
...},
...)
I'm developing a Python application using wxPython and freezing it using cxFreeze. All seems to be going fine apart from this following bit:
When I run the executable created by cxFreeze, a blank console window pops up. I don't want to show it. Is there any way I could hide it?
It doesn't seem to be documented on the cxFreeze site and Googling didn't turn up much apart from some similar sorta problems with Py2Exe.
Thanks.
For Windows:
You have to use a line like this (use file folders and names as appropriate)
C:/Python/Scripts/cxfreeze C:/Python/Code/yourprogram.py --base-name=Win32GUI --target-dir C:/Python/Dist
By adding the --base-name=Win32GUI option, the console window will not appear.
This worked to some extent but it has issues. My program runs in both a console mode and a GUI mode. When run from the console with a --console argument it runs in a console mode. When I followed the procedure below, this doesn't work anymore and my program is only a GUI app then.
The following source code comes from a sample file in the \Python\Lib\site-packages\cx_Freeze\samples\PyQt4\setup.py. Lesson of the day. Read the README.
# A simple setup script to create an executable using PyQt4. This also
# demonstrates the method for creating a Windows executable that does not have
# an associated console.
#
# PyQt4app.py is a very simple type of PyQt4 application
#
# Run the build process by running the command 'python setup.py build'
#
# If everything works well you should find a subdirectory in the build
# subdirectory that contains the files needed to run the application
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(
name = "simple_PyQt4",
version = "0.1",
description = "Sample cx_Freeze PyQt4 script",
executables = [Executable("PyQt4app.py", base = base)])
If you're using Windows, you could rename your "main" script's extension (that launches the app) to .pyw
Option 1) Use gui2exe to muck with various options.
Option 2) Modify your setup.py with 'base' parameter as such.
GUI2Exe_Target_1 = Executable(
# what to build
script = "rf_spi.py",
initScript = None,
base = 'Win32GUI', # <-- add this
targetDir = r"dist",
targetName = "rf_spi.exe",
compress = True,
copyDependentFiles = False,
appendScriptToExe = False,
appendScriptToLibrary = False,
icon = r"wireless.ico"
)