Troubleshooting py2exe packaging problem - python

I've written a setup.py script for py2exe, generated an executable for my python GUI application and I have a whole bunch of files in the dist directory, including the app, w9xopen.exe and MSVCR71.dll. When I try to run the application, I get an error message that just says "see the logfile for details". The only problem is, the log file is empty.
The closest error I've seen is "The following modules appear to be missing" but I'm not using any of those modules as far as I know (especially since they seem to be of databases I'm not using) but digging up on Google suggests that these are relatively benign warnings.
I've written and packaged a console application as well as a wxpython one with py2exe and both applications have compiled and run successfully. I am using a new python toolkit called dabo, which in turn makes uses of wxpython modules so I can't figure out what I'm doing wrong. Where do I start investigating the problem since obviously the log file hasn't been too useful?
Edit 1:
The python version is 2.5. py2exe is 0.6.8. There were no significant build errors. The only one was the bit about "The following modules appear to be missing..." which were non critical errors since the packages listed were ones I was definitely not using and shouldn't stop the execution of the app either. Running the executable produced a logfile which was completely empty. Previously it had an error about locales which I've since fixed but clearly something is wrong as the executable wasn't running. The setup.py file is based quite heavily on the original setup.py generated by running their "app wizard" and looking at the example that Ed Leafe and some others posted. Yes, I have a log file and it's not printing anything for me to use, which is why I'm asking if there's any other troubleshooting avenue I've missed which will help me find out what's going on.
I have even written a bare bones test application which simply produces a bare bones GUI - an empty frame with some default menu options. The code written itself is only 3 lines and the rest is in the 3rd party toolkit. Again, that compiled into an exe (as did my original app) but simply did not run. There were no error output in the run time log file either.
Edit 2:
It turns out that switching from "windows" to "console" for initial debugging purposes was insightful. I've now got a basic running test app and on to compiling the real app!
The test app:
import dabo
app = dabo.dApp()
app.start()
The setup.py for test app:
import os
import sys
import glob
from distutils.core import setup
import py2exe
import dabo.icons
daboDir = os.path.split(dabo.__file__)[0]
# Find the location of the dabo icons:
iconDir = os.path.split(dabo.icons.__file__)[0]
iconSubDirs = []
def getIconSubDir(arg, dirname, fnames):
if ".svn" not in dirname and dirname[-1] != "\\":
icons = glob.glob(os.path.join(dirname, "*.png"))
if icons:
subdir = (os.path.join("resources", dirname[len(arg)+1:]), icons)
iconSubDirs.append(subdir)
os.path.walk(iconDir, getIconSubDir, iconDir)
# locales:
localeDir = "%s%slocale" % (daboDir, os.sep)
locales = []
def getLocales(arg, dirname, fnames):
if ".svn" not in dirname and dirname[-1] != "\\":
mo_files = tuple(glob.glob(os.path.join(dirname, "*.mo")))
if mo_files:
subdir = os.path.join("dabo.locale", dirname[len(arg)+1:])
locales.append((subdir, mo_files))
os.path.walk(localeDir, getLocales, localeDir)
data_files=[("resources", glob.glob(os.path.join(iconDir, "*.ico"))),
("resources", glob.glob("resources/*"))]
data_files.extend(iconSubDirs)
data_files.extend(locales)
setup(name="basicApp",
version='0.01',
description="Test Dabo Application",
options={"py2exe": {
"compressed": 1, "optimize": 2, "bundle_files": 1,
"excludes": ["Tkconstants","Tkinter","tcl",
"_imagingtk", "PIL._imagingtk",
"ImageTk", "PIL.ImageTk", "FixTk", "kinterbasdb",
"MySQLdb", 'Numeric', 'OpenGL.GL', 'OpenGL.GLUT',
'dbGadfly', 'email.Generator',
'email.Iterators', 'email.Utils', 'kinterbasdb',
'numarray', 'pymssql', 'pysqlite2', 'wx.BitmapFromImage'],
"includes": ["encodings", "locale", "wx.gizmos","wx.lib.calendar"]}},
zipfile=None,
windows=[{'script':'basicApp.py'}],
data_files=data_files
)

You may need to fix log handling first, this URL may help.
Later you may look for answer here.
My answer is very general because you didn't give any more specific info (like py2exe/python version, py2exe log, other used 3rd party libraries).

See http://www.wxpython.org/docs/api/wx.App-class.html for wxPyton's App class initializer. If you want to run the app from a console and have stderr print to there, then supply False for the redirect argument. Otherwise, if you just want a window to pop up, set redirect to True and filename to None.

Related

Making .py to .exe with py2exe: can't run program [duplicate]

I thought I heard that py2exe was able to do this, but I never figured it out. Has anyone successfully done this? Can I see your setup.py file, and what command line options you used?
Basically I'm thinking of it giving me a single executable file that does something like unzips itself to maybe /temp and runs.
The way to do this using py2exe is to use the bundle_files option in your setup.py file. For a single file you will want to set bundle_files to 1, compressed to True, and set the zipfile option to None. That way it creates one compressed file for easy distribution.
Here is a more complete description of the bundle_file option quoted directly from the py2exe site*
Using "bundle_files" and "zipfile"
An easier (and better) way to create
single-file executables is to set
bundle_files to 1 or 2, and to set
zipfile to None. This approach does
not require extracting files to a
temporary location, which provides
much faster program startup.
Valid values for bundle_files are:
3 (default) don't bundle
2 bundle everything but the Python interpreter
1 bundle everything, including the Python interpreter
If zipfile is set to None, the files will be bundle
within the executable instead of library.zip.
Here is a sample setup.py:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
windows = [{'script': "single.py"}],
zipfile = None,
)
PyInstaller will create a single .exe file with no dependencies; use the --onefile option. It does this by packing all the needed shared libs into the executable, and unpacking them before it runs, just as you describe (EDIT: py2exe also has this feature, see minty's answer)
I use the version of PyInstaller from svn, since the latest release (1.3) is somewhat outdated. It's been working really well for an app which depends on PyQt, PyQwt, numpy, scipy and a few more.
As the other poster mention, py2exe, will generate an executable + some libraries to load. You can also have some data to add to your program.
Next step is to use an installer, to package all this into one easy-to-use installable/unistallable program.
I have used InnoSetup with delight for several years and for commercial programs, so I heartily recommend it.
I've been able to create a single exe file with all resources embeded into the exe.
I'm building on windows. so that will explain some of the os.system calls i'm using.
First I tried converting all my images into bitmats and then all my data files into text strings.
but this caused the final exe to be very very large.
After googleing for a week i figured out how to alter py2exe script to meet my needs.
here is the patch link on sourceforge i submitted, please post comments so we can get it included in
the next distribution.
http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583
this explanes all the changes made, i've simply added a new option to the setup line.
here is my setup.py.
i'll try to comment it as best I can.
Please know that my setup.py is complex do to the fact that i'm access the images by filename.
so I must store a list to keep track of them.
this is from a want-to-b screen saver I was trying to make.
I use exec to generate my setup at run time, its easyer to cut and paste like that.
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
breakdown
script = py script i want to turn to an exe
icon_resources = the icon for the exe
file_resources = files I want to embed into the exe
other_resources = a string to embed into the exe, in this case a file list.
options = py2exe options for creating everything into one exe file
bitmap_strings = a list of files to include
Please note that file_resources is not a valid option untill you edit your py2exe.py file as described in the link above.
first time i've tried to post code on this site, if I get it wrong don't flame me.
from distutils.core import setup
import py2exe ##UnusedImport
import os
#delete the old build drive
os.system("rmdir /s /q dist")
#setup my option for single file output
py2exe_options = dict( ascii=True, # Exclude encodings
excludes=['_ssl', # Exclude _ssl
'pyreadline', 'difflib', 'doctest', 'locale',
'optparse', 'pickle', 'calendar', 'pbd', 'unittest', 'inspect'], # Exclude standard library
dll_excludes=['msvcr71.dll', 'w9xpopen.exe',
'API-MS-Win-Core-LocalRegistry-L1-1-0.dll',
'API-MS-Win-Core-ProcessThreads-L1-1-0.dll',
'API-MS-Win-Security-Base-L1-1-0.dll',
'KERNELBASE.dll',
'POWRPROF.dll',
],
#compressed=None, # Compress library.zip
bundle_files = 1,
optimize = 2
)
#storage for the images
bitmap_string = ''
resource_string = ''
index = 0
print "compile image list"
for image_name in os.listdir('images/'):
if image_name.endswith('.jpg'):
bitmap_string += "( " + str(index+1) + "," + "'" + 'images/' + image_name + "'),"
resource_string += image_name + " "
index += 1
print "Starting build\n"
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
print "Removing Trash"
os.system("rmdir /s /q build")
os.system("del /q *.pyc")
print "Build Complete"
ok, thats it for the setup.py
now the magic needed access the images.
I developed this app without py2exe in mind then added it later.
so you'll see access for both situations. if the image folder can't be found
it tries to pull the images from the exe resources. the code will explain it.
this is part of my sprite class and it uses a directx. but you can use any api you want or just access the raw data.
doesn't matter.
def init(self):
frame = self.env.frame
use_resource_builtin = True
if os.path.isdir(SPRITES_FOLDER):
use_resource_builtin = False
else:
image_list = LoadResource(0, u'INDEX', 1).split(' ')
for (model, file) in SPRITES.items():
texture = POINTER(IDirect3DTexture9)()
if use_resource_builtin:
data = LoadResource(0, win32con.RT_RCDATA, image_list.index(file)+1) #windll.kernel32.FindResourceW(hmod,typersc,idrsc)
d3dxdll.D3DXCreateTextureFromFileInMemory(frame.device, #Pointer to an IDirect3DDevice9 interface
data, #Pointer to the file in memory
len(data), #Size of the file in memory
byref(texture)) #ppTexture
else:
d3dxdll.D3DXCreateTextureFromFileA(frame.device, ##UndefinedVariable
SPRITES_FOLDER + file,
byref(texture))
self.model_sprites[model] = texture
#else:
# raise Exception("'sprites' folder is not present!")
Any questions fell free to ask.
You should create an installer, as mentioned before. Even though it is also possible to let py2exe bundle everything into a single executable, by setting bundle_files option to 1 and the zipfile keyword argument to None, I don't recommend this for PyGTK applications.
That's because of GTK+ tries to load its data files (locals, themes, etc.) from the directory it was loaded from. So you have to make sure that the directory of your executable contains also the libraries used by GTK+ and the directories lib, share and etc from your installation of GTK+. Otherwise you will get problems running your application on a machine where GTK+ is not installed system-wide.
For more details read my guide to py2exe for PyGTK applications. It also explains how to bundle everything, but GTK+.
I'm told bbfreeze will create a single file .EXE, and is newer than py2exe.
I recently used py2exe to create an executable for post-review for sending reviews to ReviewBoard.
This was the setup.py I used
from distutils.core import setup
import py2exe
setup(console=['post-review'])
It created a directory containing the exe file and the libraries needed. I don't think it is possible to use py2exe to get just a single .exe file. If you need that you will need to first use py2exe and then use some form of installer to make the final executable.
One thing to take care of is that any egg files you use in your application need to be unzipped, otherwise py2exe can't include them. This is covered in the py2exe docs.
try
c_x freeze
it can create a good standalone

Export PyDev Pygame project as .exe? [duplicate]

I thought I heard that py2exe was able to do this, but I never figured it out. Has anyone successfully done this? Can I see your setup.py file, and what command line options you used?
Basically I'm thinking of it giving me a single executable file that does something like unzips itself to maybe /temp and runs.
The way to do this using py2exe is to use the bundle_files option in your setup.py file. For a single file you will want to set bundle_files to 1, compressed to True, and set the zipfile option to None. That way it creates one compressed file for easy distribution.
Here is a more complete description of the bundle_file option quoted directly from the py2exe site*
Using "bundle_files" and "zipfile"
An easier (and better) way to create
single-file executables is to set
bundle_files to 1 or 2, and to set
zipfile to None. This approach does
not require extracting files to a
temporary location, which provides
much faster program startup.
Valid values for bundle_files are:
3 (default) don't bundle
2 bundle everything but the Python interpreter
1 bundle everything, including the Python interpreter
If zipfile is set to None, the files will be bundle
within the executable instead of library.zip.
Here is a sample setup.py:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
windows = [{'script': "single.py"}],
zipfile = None,
)
PyInstaller will create a single .exe file with no dependencies; use the --onefile option. It does this by packing all the needed shared libs into the executable, and unpacking them before it runs, just as you describe (EDIT: py2exe also has this feature, see minty's answer)
I use the version of PyInstaller from svn, since the latest release (1.3) is somewhat outdated. It's been working really well for an app which depends on PyQt, PyQwt, numpy, scipy and a few more.
As the other poster mention, py2exe, will generate an executable + some libraries to load. You can also have some data to add to your program.
Next step is to use an installer, to package all this into one easy-to-use installable/unistallable program.
I have used InnoSetup with delight for several years and for commercial programs, so I heartily recommend it.
I've been able to create a single exe file with all resources embeded into the exe.
I'm building on windows. so that will explain some of the os.system calls i'm using.
First I tried converting all my images into bitmats and then all my data files into text strings.
but this caused the final exe to be very very large.
After googleing for a week i figured out how to alter py2exe script to meet my needs.
here is the patch link on sourceforge i submitted, please post comments so we can get it included in
the next distribution.
http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583
this explanes all the changes made, i've simply added a new option to the setup line.
here is my setup.py.
i'll try to comment it as best I can.
Please know that my setup.py is complex do to the fact that i'm access the images by filename.
so I must store a list to keep track of them.
this is from a want-to-b screen saver I was trying to make.
I use exec to generate my setup at run time, its easyer to cut and paste like that.
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
breakdown
script = py script i want to turn to an exe
icon_resources = the icon for the exe
file_resources = files I want to embed into the exe
other_resources = a string to embed into the exe, in this case a file list.
options = py2exe options for creating everything into one exe file
bitmap_strings = a list of files to include
Please note that file_resources is not a valid option untill you edit your py2exe.py file as described in the link above.
first time i've tried to post code on this site, if I get it wrong don't flame me.
from distutils.core import setup
import py2exe ##UnusedImport
import os
#delete the old build drive
os.system("rmdir /s /q dist")
#setup my option for single file output
py2exe_options = dict( ascii=True, # Exclude encodings
excludes=['_ssl', # Exclude _ssl
'pyreadline', 'difflib', 'doctest', 'locale',
'optparse', 'pickle', 'calendar', 'pbd', 'unittest', 'inspect'], # Exclude standard library
dll_excludes=['msvcr71.dll', 'w9xpopen.exe',
'API-MS-Win-Core-LocalRegistry-L1-1-0.dll',
'API-MS-Win-Core-ProcessThreads-L1-1-0.dll',
'API-MS-Win-Security-Base-L1-1-0.dll',
'KERNELBASE.dll',
'POWRPROF.dll',
],
#compressed=None, # Compress library.zip
bundle_files = 1,
optimize = 2
)
#storage for the images
bitmap_string = ''
resource_string = ''
index = 0
print "compile image list"
for image_name in os.listdir('images/'):
if image_name.endswith('.jpg'):
bitmap_string += "( " + str(index+1) + "," + "'" + 'images/' + image_name + "'),"
resource_string += image_name + " "
index += 1
print "Starting build\n"
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
print "Removing Trash"
os.system("rmdir /s /q build")
os.system("del /q *.pyc")
print "Build Complete"
ok, thats it for the setup.py
now the magic needed access the images.
I developed this app without py2exe in mind then added it later.
so you'll see access for both situations. if the image folder can't be found
it tries to pull the images from the exe resources. the code will explain it.
this is part of my sprite class and it uses a directx. but you can use any api you want or just access the raw data.
doesn't matter.
def init(self):
frame = self.env.frame
use_resource_builtin = True
if os.path.isdir(SPRITES_FOLDER):
use_resource_builtin = False
else:
image_list = LoadResource(0, u'INDEX', 1).split(' ')
for (model, file) in SPRITES.items():
texture = POINTER(IDirect3DTexture9)()
if use_resource_builtin:
data = LoadResource(0, win32con.RT_RCDATA, image_list.index(file)+1) #windll.kernel32.FindResourceW(hmod,typersc,idrsc)
d3dxdll.D3DXCreateTextureFromFileInMemory(frame.device, #Pointer to an IDirect3DDevice9 interface
data, #Pointer to the file in memory
len(data), #Size of the file in memory
byref(texture)) #ppTexture
else:
d3dxdll.D3DXCreateTextureFromFileA(frame.device, ##UndefinedVariable
SPRITES_FOLDER + file,
byref(texture))
self.model_sprites[model] = texture
#else:
# raise Exception("'sprites' folder is not present!")
Any questions fell free to ask.
You should create an installer, as mentioned before. Even though it is also possible to let py2exe bundle everything into a single executable, by setting bundle_files option to 1 and the zipfile keyword argument to None, I don't recommend this for PyGTK applications.
That's because of GTK+ tries to load its data files (locals, themes, etc.) from the directory it was loaded from. So you have to make sure that the directory of your executable contains also the libraries used by GTK+ and the directories lib, share and etc from your installation of GTK+. Otherwise you will get problems running your application on a machine where GTK+ is not installed system-wide.
For more details read my guide to py2exe for PyGTK applications. It also explains how to bundle everything, but GTK+.
I'm told bbfreeze will create a single file .EXE, and is newer than py2exe.
I recently used py2exe to create an executable for post-review for sending reviews to ReviewBoard.
This was the setup.py I used
from distutils.core import setup
import py2exe
setup(console=['post-review'])
It created a directory containing the exe file and the libraries needed. I don't think it is possible to use py2exe to get just a single .exe file. If you need that you will need to first use py2exe and then use some form of installer to make the final executable.
One thing to take care of is that any egg files you use in your application need to be unzipped, otherwise py2exe can't include them. This is covered in the py2exe docs.
try
c_x freeze
it can create a good standalone

Extend the functionality of a compiled Python script

I'm not a programmer, so I don't even know in what terms should I ask this. Let's say I've compiled a Python script to have an .exe (I use py2exe to do this). This is the major program. Now, I want to add some extra functionality to it, but I don't want to recompile the entire script with the added functionality. I tried to search something on the web, and I found examples of extending a C++ or other application with Python scripts (like a sort of plugin). But I can't figure out how to do it with an application already written in Python.
I tried this: I wrote major.py (this is the script from where I build the executable) and stuff.py. In major I wrote this:
def generic():
import stuff
while True:
param=input('what did you say? ')
stuff.speak(param)
generic()
And in stuff I wrote this:
def speak(param):
print(param)
Then I created a .exe with py2exe. It works as expected, when I run the program in the command line says "what did you say?" and waits until I type something, then it prints what I typed.
Then, I changed stuff.py with this:
def speak(param):
print('I said '+param)
Hoping that now upon the execution of the .exe created earlier it would print "I said.." plus whatever I typed. Obviously, it didn't work, the program continued to behave like before. So I'm guessing that once I imported stuff and created the .exe file, that import is permanent, not allowing me to change whatever is in stuff. What should I do?
py2exe packs the compiled scripts in the executable.
You need to recreate the executable (which will recompile any changed script) to see the changes take effect.
EDIT following the comments:
You can do it if you dynamically import/reimport the module from inside the executable.
In your main script you do (see code below)
mod, error = loadmodule('mystuff.py')
if mod is not None:
# loading succeeded you can now proceed and do things with it
pass
Of course you have to leave mystuff.py out of the scripts that py2exe packs into the executable. In the above example mystuff.py would be in the same directory as the executable.
The loading code:
def loadmodule(modpath, modname=''):
if not modpath.endswith('.py'):
modpath += '.py'
# generate a random name for the module
if not modname:
modpathbase = os.path.basename(modpath)
modname, _ = os.path.splitext(modpathbase)
version = (sys.version_info[0], sys.version_info[1])
if version < (3, 3):
mod, e = loadmodule2(modpath, modname)
else:
mod, e = loadmodule3(modpath, modname)
return mod, e
def loadmodule2(modpath, modname):
import imp
try:
mod = imp.load_source(modname, modpath)
except Exception as e:
return (None, e)
return (mod, None)
def loadmodule3(modpath, modname):
import importlib.machinery
try:
loader = importlib.machinery.SourceFileLoader(modname, modpath)
mod = loader.load_module()
except Exception as e:
return (None, e)
return (mod, None)
If you run your script from Python, instead of compiling it as an executable, you can make changes and run them without having to recompile. The py2exe is mostly for allowing you to distribute your application to other Windows computers that don't have Python installed. After you have finished developing it, then compile it as an executable so you can run it on other computers.
There is no way to do what you want. py2exe builds a standalone python interpreter (In the file named python.dll) with just the dependencies of your project. Then the .exe file runs your script using that interpreter
I suggest you that if you really need to provide regular upgrades then you should recompile it, or install python in the target machine, or make an updating routine that checks for updates and compiles it in the target machine (With py2exe)

Python Scapy and Pyinstaller

I'm trying to create simple executable with pyinstaller from script I use for testing so I do not have to install everything on server I'm testing from.
#! /usr/bin/env python
from scapy.all import *
sourceport=int(raw_input('Soruce port:'))
destinationport=int(raw_input('Destination port:'))
destinationip=raw_input('Destination IP:')
maxttl=int(raw_input('MAX TTL:'))
for i in range(1,maxttl):
udptrace = IP(dst=destinationip,ttl=i)/UDP(dport=destinationport,sport=sourceport,len=500)
received=sr1(udptrace,verbose=0,timeout=2)
try:
print received.summary()
except AttributeError:
print "** TIMEOUT **"
Then I make executable:
pyinstaller -F udp.py
However when I run it and I have the following error:
Soruce port:500
Destination port:500
Destination IP:4.4.4.4
MAX TTL:3
Traceback (most recent call last):
File "<string>", line 16, in <module>
NameError: name 'IP' is not defined
user#:~/2/dist$
I have spent some time researching but did not find any answers.
The problem
First, we need to pinpoint the exact problem.
The PyInstaller manual specifies that:
Some Python scripts import modules in ways that PyInstaller cannot detect: for example, by using the __import__() function with variable data.
Inspecting Scapy's source code reveals that this is exactly how the various networking layers are imported:
scapy/layers/all.py:
def _import_star(m):
mod = __import__(m, globals(), locals())
for k,v in mod.__dict__.iteritems():
globals()[k] = v
for _l in conf.load_layers:
log_loading.debug("Loading layer %s" % _l)
try:
_import_star(_l)
except Exception,e:
log.warning("can't import layer %s: %s" % (_l,e))
Note that __import__ is invoked for each module in conf.load_layers.
scapy/config.py:
class Conf(ConfClass):
"""This object contains the configuration of scapy."""
load_layers = ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp",
"mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp",
"sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp",
"ipsec" ]
Note that Conf.load_layers contains "inet".
The file scapy/layers/inet.py defines the IP class, which was not imported successfully in the enclosed example.
The solution
Now, that we have located the root cause, let's see what can be done about it.
The PyInstaller manual suggests some workarounds to such importing issues:
You can give additional files on the PyInstaller command line.
You can give additional import paths on the command line.
You can edit the myscript.spec file that PyInstaller writes the first time you run it for your script. In the spec file you can tell PyInstaller about code and data files that are unique to your script.
You can write "hook" files that inform PyInstaller of hidden imports. If you "hook" imports for a package that other users might also use, you can contribute your hook file to PyInstaller.
A bit of googling reveals that an appropriate "hook" was already added to the default PyInstaller distribution, in this commit, which introduced the file PyInstaller/hooks/hook-scapy.layers.all.py.
The PyInstaller manuals indicates that such built-in hooks should run automatically:
In summary, a "hook" file tells PyInstaller about hidden imports called by a particular module. The name of the hook file is hook-<module>.py where "<module>" is the name of a script or imported module that will be found by Analysis. You should browse through the existing hooks in the hooks folder of the PyInstaller distribution folder, if only to see the names of the many supported imports.
For example hook-cPickle.py is a hook file telling about hidden imports used by the module cPickle. When your script has import cPickle the Analysis will note it and check for a hook file hook-cPickle.py.
Bottom Line
Therefore, please verify that you're running the latest version of PyInstaller. If you can't upgrade to the latest version, or if it doesn't contain the file PyInstaller/hooks/hook-scapy.layers.all.py, then create it with the following content:
#-----------------------------------------------------------------------------
# Copyright (c) 2013, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
from PyInstaller.hooks.hookutils import collect_submodules
# The layers to load can be configured using scapy's conf.load_layers.
# from scapy.config import conf; print(conf.load_layers)
# I decided not to use this, but to include all layer modules. The
# reason is: When building the package, load_layers may not include
# all the layer modules the program will use later.
hiddenimports = collect_submodules('scapy.layers')

py2exe - single exe file result [duplicate]

I thought I heard that py2exe was able to do this, but I never figured it out. Has anyone successfully done this? Can I see your setup.py file, and what command line options you used?
Basically I'm thinking of it giving me a single executable file that does something like unzips itself to maybe /temp and runs.
The way to do this using py2exe is to use the bundle_files option in your setup.py file. For a single file you will want to set bundle_files to 1, compressed to True, and set the zipfile option to None. That way it creates one compressed file for easy distribution.
Here is a more complete description of the bundle_file option quoted directly from the py2exe site*
Using "bundle_files" and "zipfile"
An easier (and better) way to create
single-file executables is to set
bundle_files to 1 or 2, and to set
zipfile to None. This approach does
not require extracting files to a
temporary location, which provides
much faster program startup.
Valid values for bundle_files are:
3 (default) don't bundle
2 bundle everything but the Python interpreter
1 bundle everything, including the Python interpreter
If zipfile is set to None, the files will be bundle
within the executable instead of library.zip.
Here is a sample setup.py:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
windows = [{'script': "single.py"}],
zipfile = None,
)
PyInstaller will create a single .exe file with no dependencies; use the --onefile option. It does this by packing all the needed shared libs into the executable, and unpacking them before it runs, just as you describe (EDIT: py2exe also has this feature, see minty's answer)
I use the version of PyInstaller from svn, since the latest release (1.3) is somewhat outdated. It's been working really well for an app which depends on PyQt, PyQwt, numpy, scipy and a few more.
As the other poster mention, py2exe, will generate an executable + some libraries to load. You can also have some data to add to your program.
Next step is to use an installer, to package all this into one easy-to-use installable/unistallable program.
I have used InnoSetup with delight for several years and for commercial programs, so I heartily recommend it.
I've been able to create a single exe file with all resources embeded into the exe.
I'm building on windows. so that will explain some of the os.system calls i'm using.
First I tried converting all my images into bitmats and then all my data files into text strings.
but this caused the final exe to be very very large.
After googleing for a week i figured out how to alter py2exe script to meet my needs.
here is the patch link on sourceforge i submitted, please post comments so we can get it included in
the next distribution.
http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583
this explanes all the changes made, i've simply added a new option to the setup line.
here is my setup.py.
i'll try to comment it as best I can.
Please know that my setup.py is complex do to the fact that i'm access the images by filename.
so I must store a list to keep track of them.
this is from a want-to-b screen saver I was trying to make.
I use exec to generate my setup at run time, its easyer to cut and paste like that.
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
breakdown
script = py script i want to turn to an exe
icon_resources = the icon for the exe
file_resources = files I want to embed into the exe
other_resources = a string to embed into the exe, in this case a file list.
options = py2exe options for creating everything into one exe file
bitmap_strings = a list of files to include
Please note that file_resources is not a valid option untill you edit your py2exe.py file as described in the link above.
first time i've tried to post code on this site, if I get it wrong don't flame me.
from distutils.core import setup
import py2exe ##UnusedImport
import os
#delete the old build drive
os.system("rmdir /s /q dist")
#setup my option for single file output
py2exe_options = dict( ascii=True, # Exclude encodings
excludes=['_ssl', # Exclude _ssl
'pyreadline', 'difflib', 'doctest', 'locale',
'optparse', 'pickle', 'calendar', 'pbd', 'unittest', 'inspect'], # Exclude standard library
dll_excludes=['msvcr71.dll', 'w9xpopen.exe',
'API-MS-Win-Core-LocalRegistry-L1-1-0.dll',
'API-MS-Win-Core-ProcessThreads-L1-1-0.dll',
'API-MS-Win-Security-Base-L1-1-0.dll',
'KERNELBASE.dll',
'POWRPROF.dll',
],
#compressed=None, # Compress library.zip
bundle_files = 1,
optimize = 2
)
#storage for the images
bitmap_string = ''
resource_string = ''
index = 0
print "compile image list"
for image_name in os.listdir('images/'):
if image_name.endswith('.jpg'):
bitmap_string += "( " + str(index+1) + "," + "'" + 'images/' + image_name + "'),"
resource_string += image_name + " "
index += 1
print "Starting build\n"
exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
options={'py2exe': py2exe_options},\
zipfile = None )" % (bitmap_string[:-1])
print "Removing Trash"
os.system("rmdir /s /q build")
os.system("del /q *.pyc")
print "Build Complete"
ok, thats it for the setup.py
now the magic needed access the images.
I developed this app without py2exe in mind then added it later.
so you'll see access for both situations. if the image folder can't be found
it tries to pull the images from the exe resources. the code will explain it.
this is part of my sprite class and it uses a directx. but you can use any api you want or just access the raw data.
doesn't matter.
def init(self):
frame = self.env.frame
use_resource_builtin = True
if os.path.isdir(SPRITES_FOLDER):
use_resource_builtin = False
else:
image_list = LoadResource(0, u'INDEX', 1).split(' ')
for (model, file) in SPRITES.items():
texture = POINTER(IDirect3DTexture9)()
if use_resource_builtin:
data = LoadResource(0, win32con.RT_RCDATA, image_list.index(file)+1) #windll.kernel32.FindResourceW(hmod,typersc,idrsc)
d3dxdll.D3DXCreateTextureFromFileInMemory(frame.device, #Pointer to an IDirect3DDevice9 interface
data, #Pointer to the file in memory
len(data), #Size of the file in memory
byref(texture)) #ppTexture
else:
d3dxdll.D3DXCreateTextureFromFileA(frame.device, ##UndefinedVariable
SPRITES_FOLDER + file,
byref(texture))
self.model_sprites[model] = texture
#else:
# raise Exception("'sprites' folder is not present!")
Any questions fell free to ask.
You should create an installer, as mentioned before. Even though it is also possible to let py2exe bundle everything into a single executable, by setting bundle_files option to 1 and the zipfile keyword argument to None, I don't recommend this for PyGTK applications.
That's because of GTK+ tries to load its data files (locals, themes, etc.) from the directory it was loaded from. So you have to make sure that the directory of your executable contains also the libraries used by GTK+ and the directories lib, share and etc from your installation of GTK+. Otherwise you will get problems running your application on a machine where GTK+ is not installed system-wide.
For more details read my guide to py2exe for PyGTK applications. It also explains how to bundle everything, but GTK+.
I'm told bbfreeze will create a single file .EXE, and is newer than py2exe.
I recently used py2exe to create an executable for post-review for sending reviews to ReviewBoard.
This was the setup.py I used
from distutils.core import setup
import py2exe
setup(console=['post-review'])
It created a directory containing the exe file and the libraries needed. I don't think it is possible to use py2exe to get just a single .exe file. If you need that you will need to first use py2exe and then use some form of installer to make the final executable.
One thing to take care of is that any egg files you use in your application need to be unzipped, otherwise py2exe can't include them. This is covered in the py2exe docs.
try
c_x freeze
it can create a good standalone

Categories

Resources