Bundle sqldrivers into .exe using py2exe - python

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.

Related

Python Flask - Building the Server as Executable (Py2exe)

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.

Working with cx_Freeze - how to include all necessary files in .exe?

I want to make a self-contained .exe file.
I have managed to use cx_Freeze to build one that works on my machine, but it is throwing an error about needing the .dlls when I sent it to someone. I read a few of the similar questions, which is how I ended up including packages in the build options.
I suspect that once I get past this particular problem, I will end up needing to include other stuff in the .exe....any help getting around that pitfall is appreciated! The end user needs to be able to only use the .exe and not have to install other files.
Here is my current setup.py:
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
build_options = {"includes" : [ "re", "atexit"], "packages": ["PyQt4.QtCore", "PyQt4.QtGui"]}
setup( name = "Hex Script Combination",
version = "0.1",
description = "Contact (info) with questions",
options = {"build_exe" : build_options},
executables = [Executable("Project.py", base=base)])
ETA:
I tried IExpress, and I'm running into this error:
(Picture uploaded but for some reason, neither picture in this post is showing)
File "C:\Python27\lib\site-packages\cx_Freeze\initscripts\Console.py", line 26, in <module>
code = importer.get_code(moduleName)
ZipImportError: can't find module 'projec~1__main__'
I did NOT find a way to do exactly what I wanted. I did, however, discover that I was getting an installer I wasn't aware of for distribution that did install everything that was in my exe directory.
File path was ~\dist, and it contained only an .msi file. Launching it installed everything that was in ~\build\exe.win32-2.7

Compiling docx with py2exe

I'm compiling a python script to .exe via py2exe. I originally started compiling it and the entire program ran fine aside from the Word document creation.
My logfile would give me: ERROR: Could not close or save Word Document 'docName.docx' :, so where I am supposed to be supplied an error message - I am not.
I started to think it could do with the missing modules in py2exe, reported as:
The following modules appear to be missing
['ICCProfile', '_imaging_gif', '_scproxy', '_sysconfigdata']
And then I noticed many people didn't care too much about these errors.
I looked in the docx package, located in C:\Python27\Lib\site-packages\docx-0.2.4-py2.7.egg\, as installed by easy_install, and saw this docx-templates folder, which I am certain was not imported, so I wrote my setup.py referencing the docx-template I put in my build folder manually:
from distutils.core import setup
from glob import glob
import os
import py2exe
#templatePath = 'C:/Python27/Lib/site-packages/docx-0.2.4-py2.7.egg/docx-template'
setup(
console=['xmlpolicydocx-0.4.py'],
options={
'py2exe':
{
'includes': ['docx', 'PIL', 'lxml.etree', 'lxml._elementpath', 'gzip']
}
},
packages=[
'docx-template'
],
package_data={
'docx-template': [
'_rels/*',
'docProps/*',
'word/theme/*.xml',
'word/*.xml'
],
},
)
Yet I still have no luck in getting docx to work when compiled via py2exe. Any suggestions or methods of debugging I can take to take another look at solving this problem?

Where to put images folder in python exe?

I have converted a python game I designed into an exe. Running the exe itself causes it to flash and then close, meaning an error has occured. Running it from the Command Prompt causes the error as well, but documents it:
Cannot load image: Playfield.png
Couldn't open images\Playfield.png
This is telling me that the load_image block is failing. I have encountered this before when I did not have an images directory.
I attempted to move the images folder to the dist directory. This is the error that shows up:
Traceback (most recent call last):
File "Table_Wars.py", line 728, in <module>
File "Table_Wars.py", line 51, in main
File "Table_Wars.py", line 236, in __init__
File "pygame\__init__.pyc", line 70, in __getattr__
NotImplementedError: font module not available
(ImportError: DLL load failed: The specified module could not be found.)
This is my first time with py2exe, so I'm not really sure what is happening. The raw python file itself, Table_Wars.py, runs as expected.
If it helps, the location for the entire Table_Wars folder is inside a folder called Games, located on my Desktop (C:\Users\Oventoaster\Desktop\Games\Table_Wars). I am running Windows 7 32 bit OS.
On request, here is the output.txt I have generated:
Folder PATH listing for volume OS
Volume serial number is 7659-4C9C
C:\USERS\OVENTOASTER\DESKTOP\GAMES\TABLE_WARS
build
bdist.win32
winexe
bundle-2.7
collect-2.7
ctypes
distutils
email
mime
encodings
logging
multiprocessing
dummy
pygame
threads
unittest
xml
parsers
temp
dist
images
Here is the setup.py I used to convert the file:
from distutils.core import setup
import py2exe
setup(console=['Table_Wars.py'])
EDIT: I have attempted to use the full py2exe example. This will create the exe, but gives the same Cannot load image error. Attempting to put the images folder in the same folder as the exe creates a Runtime Error: The application requested the runtime to terminate it in an unusual way.
The shortened form of the code Slace Diamond suggested prevents py2exe from finding Table_Wars.py:
from cmd:
running py2exe
*** searching for required modules ***
error: Table_Wars.py: No such file or directory.
setup and Table_Wars are in the same directory. If it help, I input the full path to python.exe and setup.py.
EDIT: I seem to be getting closer. I put the images directory within self.extra_datas, and now I am getting this:
Fatal Python error: (segmentation fault)
This application has requested the runtime to terminate it in an unusual way. Please contact the application's suppourt team for more information
When you build a distributable package with py2exe (and py2app for that matter), part of the package environment is to point to a local resource location for files. In your plain unpackaged version, you are referring to a relative "images/" location. For the packaged version, you need to configure your setup.py to include the resources in its own location.
Refer to this doc for very specific info about how to set the data_files option of your package: http://www.py2exe.org/index.cgi/data_files
That page has multiple examples to show both very simple paths, and also a helper function for finding the data and building the data_files list for you.
Here is an example of the simple snippet:
from distutils.core import setup
import py2exe
Mydata_files = [('images', ['c:/path/to/image/image.png'])]
setup(
console=['trypyglet.py.py']
data_files = Mydata_files
options={
"py2exe":{
"unbuffered": True,
"optimize": 2,
"excludes": ["email"]
}
}
)
This closely matches what you are trying to achieve. It is saying that the "image.png" source file should be placed into the "images" directory at the root of the resources location inside the package. This resource root will be your current directory from your python scripts, so you can continue to refer to it as a relative sub directory.
It looks like you've already fixed the image problem by moving the folder into dist. The missing font module, on the other hand, is a known problem between pygame and py2exe. Py2exe doesn't copy some necessary DLLs, so you have to override py2exe's isSystemDLL method, forcing it to include audio and font related DLLs.
If Table_Wars.py is the only module in your project, try running this script with python setup.py py2exe:
from os.path import basename
from distutils.core import setup
import py2exe
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
if basename(pathname).lower() in ("libogg-0.dll", "sdl_ttf.dll"):
return 0
return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL
setup(windows=[{"script": "Table_Wars.py"}],
options={"py2exe": {"dist_dir": "dist"}})
You could also try the example py2exe setup file on the pygame wiki. If neither of them are working, please add the error messages to your question.
I tried running py2exe on a sample project, and it also breaks for me when I use the default pygame font. If you're using the default font, try putting a ttf file in the root of your project and also in the dist folder. You'll have to change the call to pygame.Font in your script as well:
font = pygame.font.Font("SomeFont.ttf", 28)

PyQt/PySide - icon display

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
...},
...)

Categories

Resources