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
...},
...)
Related
When using cx_Freeze and Tkinter, I am given the message:
File "C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 35, in <module>
import _tkinter # If this fails your Python may not be configured for Tk
ImportError: DLL load failed: The specified module could not be found.
Some things to note:
I want to use Python 3+ (Currently using 3.5.3, 32-bit). Don't really care about a specific version, whatever works.
My project has multiple files I need to compile. As far as I can tell, that leaves me with cx_Freeze or Nuitka. Nuitka had problems of its own.
I am using Windows 10 Home Edition, 64-bit
Here is my current setup.py:
from cx_Freeze import setup, Executable
import sys
build_exe_options = {"packages": ["files", "tools"]}
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(name="Name",
version="1.0",
description="Description",
options={"build_exe": build_exe_options},
executables=[Executable("main.py", base=base)],
package_dir={'': ''},
)
I have tried many solutions from all corners of the internet. Including but not limited to:
Multiple versions of python (and the corresponding cx_Freeze/Tkinter versions)
Both 32-bit and 64-bit versions
Replacing Tkinter with easygui (apparently easygui needs Tkinter to work)
Checking the PATH variables
Restarting my computer (Don't know what I expected)
Uninstalling other versions of python and repairing the correct version
Placing the following in my compile bat file (Definetly the correct paths):
set TCL_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35-32\tcl\tcl8.6
set TK_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35-32\tcl\tk8.6
Placing the following in my setup.py:
options={"build_exe": {"includes": ["tkinter"]}}
Along with:
include_files = [r"C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35-32\DLLs\tcl86t.dll",\
r"C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35-32\DLLs\tk86t.dll"]
(And yes, those were included in setup() in one way or another)
Thanks for any help, it's greatly appreciated. And yes, I have looked at just about every solution to this problem on this site. Hoping someone could help me find yet another solution since my problem seems to be persistent.
Found a solution!
I had to copy the tk86t.dll and tcl86t.dll files from my python directory's DLLs folder into the build folder with the main.py I was trying to compile.
This, in conjunction with having
set TCL_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35\tcl\tcl8.6
set TK_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python35\tcl\tk8.6
at the top of my compile.bat, and including
"include_files": ["tcl86t.dll", "tk86t.dll"]
in my build_exe_options in setup.py, seems to have done the trick.
Here is my current setup.py:
from cx_Freeze import setup, Executable
import sys
build_exe_options = {"packages": ["files", "tools"], "include_files": ["tcl86t.dll", "tk86t.dll"]}
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup(name="Name",
version="1.0",
description="Description",
options={"build_exe": build_exe_options},
executables=[Executable("main.py", base=base)],
package_dir={'': ''},
)
And here is my compile.bat (updated to show all steps):
#echo off
set TCL_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python36-32\tcl\tcl8.6
set TK_LIBRARY=C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python36-32\tcl\tk8.6
RD /S /Q "C:\Users\VergilTheHuragok\Desktop\PythonProjectCompiled\bin"
mkdir "C:\Users\VergilTheHuragok\Desktop\PythonProjectCompiled\bin"
xcopy /s "C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python36-32\DLLs\tcl86t.dll" "C:\Users\VergilTheHuragok\Desktop\PythonProjectCompiled\bin\tcl86t.dll"
xcopy /s "C:\Users\VergilTheHuragok\AppData\Local\Programs\Python\Python36-32\DLLs\tk86t.dll" "C:\Users\VergilTheHuragok\Desktop\PythonProjectCompiled\bin\tk86t.dll"
cd "C:\Users\VergilTheHuragok\Desktop\PythonProject\"
cxfreeze main.py --target-dir "C:\Users\VergilTheHuragok\Desktop\PythonProjectCompiled\bin" --target-name "launch.exe"
pause
I found this solution here.
to solve this problem just copy the files
1.tcl86t.dll
2.tk86t.dll
from this path C:\Users\h280126\AppData\Local\Programs\Python\Python36-32\DLLs
and placed in our .exe path
C:\Users\h280126\PycharmProjects\my_tool\build\exe.win32-3.6
it is working fine :)
After fixing these issues cx_freeze was still unable to import the dependencies of pandas (namely numpy). To fix this I literally copied and pasted the entire folders into the directory of the .py file I was trying to compile. The executable needs to be in the same directory (so it isn't necessarily stand-alone) but it runs with pandas and numpy.
I have created a Tkinter GUI in Python. The following snippet shows how when the application starts it changes its icon to the one in icon.gif. This works on Ubuntu and Windows however it does not appear to do anything in Mac. If it helps I'm running Python 2.7.10 on OS X 10.9.5 with Tcl 8.5 & Tk 8.5 (8.5.18). How can I change the icon that appears in the dock?
import Tkinter as TK
class MyClass(object):
def __init__(self, root):
pass
if __name__ == '__main__':
root = TK.Tk()
my_app = MyApp(root)
icon_path = 'some\long\path\to\icon.gif'
img = TK.PhotoImage(file=icon_path)
root.tk.call('wm', 'iconphoto', root._w, img)
root.mainloop()
root.destroy()
I know this is old, but i just saw the answer before coming here and I thought I'd share the answer in case someone stumbles on this in the future and wants to know.
You must supply a icon file in the .icns format in order for your app to have an application icon. py2app has three ways of doing this:
command line argument
options dictionary in setup.py
setup.cfg file
In all following situations, replace app.icns with the full path to your desired .icns file
CLI argument
$ python setup.py py2app --iconfile app.icns
Setup.py dictionary
from setuptools import setup
APP = ['YourApp.py']
APP_NAME = "YourApp"
DATA_FILES = []
OPTIONS = {
'argv_emulation': True,
'iconfile': 'app.icns',
}
setup(
name=APP_NAME,
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
Setup.cfg
I'm honestly not sure about this one, I don't touch .cfg files
[py2app]
iconfile="app.icns"
Here is the relevant relevant documentation. A practical example is available as well.
If you mean the icon in the top left corner this might not work but to create an app for Mac with an icon you do this:
To add an icon you have to make a .icns file. Follow these or these instructions. Secondly you have to make the program into an app. To do this follow the instructions here but don't do it yet. Ok now go into setup.py and add under options 'iconfile' : 'icon.icns'. Create the app now. It will only work if you put the .icns image in the same folder as setup.py. This will add an icon to the app.
I have a flask project, everything appears to be working fine. When using py2exe to build the package, (target server is a windows server ugh), the executable can execute, but leaves me with a ImportError: No module named 'jinja2.ext'
I have the module, and the website works fine with no ImportError when not executing from the .exe
I am pretty new at packaging and delivering, and not sure whats wrong with the setup that is causing the break from .py -> .exe conversion.
Setup.py
from setuptools import setup, find_packages
import py2exe
NAME = "WorkgroupDashboard"
VERSION = "1.0"
setup(
name=NAME,
version=VERSION,
description="Provides real time ISIS connection data",
long_description="",
# Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
classifiers=[],
author="Test User",
author_email='',
url='',
license='Free',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
include_package_data=True,
zip_safe=False,
install_requires=[
'flask >= 0.10.1',
'SQLAlchemy>=0.6'
],
console=['DashboardBack.py']
)
The idea is in order to turn the server on, just execute the .exe. Server will not have python on it. I am using Python 3.4 64 bit.
Edit: build cmd = python setup.py py2exe
Figured it out it seems, Setup commands go inside the py2exe optuons=[]
Working Setup.py
__author__ = ''
import sys
from glob import glob # glob will help us search for files based on their extension or filename.
from distutils.core import setup # distutils sends the data py2exe uses to know which file compile
import py2exe
data_files = []
setup(
name='WorkgroupDashboard',
console=['DashboardBack.py'], # 'windows' means it's a GUI, 'console' It's a console program, 'service' a Windows' service, 'com_server' is for a COM server
# You can add more and py2exe will compile them separately.
options={ # This is the list of options each module has, for example py2exe, but for example, PyQt or django could also contain specific options
'py2exe': {
'packages':['jinja2'],
'dist_dir': 'dist/test', # The output folder
'compressed': True, # If you want the program to be compressed to be as small as possible
'includes':['os', 'logging', 'yaml', 'flask', 'sqlalchemy'], # All the modules you need to be included, because py2exe guesses which modules are being used by the file we want to compile, but not the imports
}
},
data_files=data_files # Finally, pass the
)
I'd convert mine to EXE and deploy is over a host. Just get "Auto Py To Exe" application. Download it locally. Open the app, insert your project location, do some setup if you want, and then click "Convert". There you go. Flask in EXE format. Plug-in anywhere that you like without the need to have Python Interpreter.
In my first attempts, my pyQt application bundled with py2exe refused to connect to the sqlite database although it was working in its python version.
I guessed that it was a problem of libraries not loaded into the .exe application. I solved that problem by including the full path to the sqlite DLL into the setup.py file and thus copying this DLL to the executable folder.
Now I would like to include this DLL into the .exe file in order to "hide" this DLL to my users. Do you have a clue how to do that ?
my current setup.py:
from distutils.core import setup
import py2exe
setup(
windows=[{
"script": 'myscript.py'
}],
options={
'py2exe': {
"dll_excludes": [
"MSVCP90.dll",
"MSWSOCK.dll",
"mswsock.dll",
"powrprof.dll",
],
'includes': [
'sip',
'PyQt4.QtNetwork',
],
'bundle_files': 1,
}
},
data_files = [
'config.ini',
'template.htm',
# This is the File that I wish to be "hidden"
('sqldrivers', ('C:\Python27\Lib\site-packages\PyQt4\plugins\sqldrivers\qsqlite4.dll',)),
zipfile=None,
)
I ran into the same problem and you are half way to solving the issue. The first part of the problem is as you identified, getting the file into the EXE. I can't speak to the correctness of your py2exe solution as I am using pyinstaller, but that is the general idea. You need to get the qsqlite4.dll into a sqldrivers directory within your single file app.
The second part is that your main .py needs to have the path added to its running directory which will now contain that sqldrivers folder. What you will need to do is get the relative path to where your main .py is running and set that directory as your library path in your QT application. I use the standard resource_path() function for pyinstaller, but using something like this should work for py2exe:
def resource_path(relative_path)
if sys.frozen:
base_path = os.path.dirname(sys.executable)
else:
base_path = os.path.dirname(__file__)
return os.path.join(base_path, relative_path)
Then you can use this code in the main function of your application
app = QApplication(sys.argv)
new_lib_path = app.libraryPaths()
new_lib_path.append(resource_path(''))
app.setLibraryPaths(new_lib_path)
. . .
With logging added, here is my app.libraryPaths() before and after:
08/25/2014 01:33:24 AM CRITICAL: Before[u'C:/dev/WORKSP~1/db/dist']
08/25/2014 01:33:24 AM CRITICAL: After[u'C:/dev/WORKSP~1/db/dist', u'C:\\Users\\jeff\\AppData\\Local\\Temp\\_MEI2042\\']
You could replace the '\' with '/' but I didn't bother, it still works with windows separators.
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.