I spent the day in py2exe hell. After grinding through six separate problems, now I'm stuck. Has anyone got this combo to work? I'm using Python 2.6 and Pygame 1.9.x and pyOpenGl 3.0.x and the latest py2exe. When I run the resulting exe, I get the following runtime error:
Traceback (most recent call last): File "main.py", line 29, in <module> File "zipextimporter.pyo", line 82, in load_module File "pygl2d\__init__.pyo", line 5, in <module> File "zipextimporter.pyo", line 82, in load_module File "pygl2d\window.pyo", line 3, in <module> File ".\OpenGL\GL\__init__.py", line 2, in <module> from OpenGL.raw.GL import * File ".\OpenGL\raw\GL\__init__.py", line 6, in <module> from OpenGL.raw.GL.constants import * File ".\OpenGL\raw\GL\constants.py", line 7, in <module> from OpenGL import platform, arrays File ".\OpenGL\arrays\__init__.py", line 22, in <module> formathandler.FormatHandler.loadAll() File ".\OpenGL\arrays\formathandler.py", line 37, in loadAll cls.loadPlugin( entrypoint ) File ".\OpenGL\arrays\formathandler.py", line 44, in loadPlugin plugin_class = entrypoint.load() File ".\OpenGL\plugins.py", line 14, in load return importByName( self.import_path ) File ".\OpenGL\plugins.py", line 28, in importByName module = __import__( ".".join(moduleName), {}, {}, moduleName) File ".\OpenGL\arrays\strings.py", line 8, in <module> psas = ctypes.pythonapi.PyString_AsString File "ctypes\__init__.pyo", line 366, in __getattr__ File "ctypes\__init__.pyo", line 371, in __getitem__ AttributeError: function 'PyString_AsString' not found Here is the script I'm currently using, based on the pygame wiki script: # This will create a dist directory containing the executable file, all the data # directories. All Libraries will be bundled in executable file. # # Run the build process by entering 'pygame2exe.py' or # 'python pygame2exe.py' in a console prompt. # # To build exe, python, pygame, and py2exe have to be installed. After # building exe none of this libraries are needed. try: from distutils.core import setup import py2exe, pygame from modulefinder import Module import glob, fnmatch import sys, os, shutil import operator except ImportError, message: raise SystemExit, "Unable to load module. %s" % message #---HACK origIsSystemDLL = py2exe.build_exe.isSystemDLL def isSystemDLL(pathname): if os.path.basename(pathname).lower() in ["sdl_ttf.dll","sdl_mixer.dll","libogg-0.dll"]: return 0 return origIsSystemDLL(pathname) py2exe.build_exe.isSystemDLL = isSystemDLL #---ENDHACK class pygame2exe(py2exe.build_exe.py2exe): #This hack make sure that pygame default font is copied: no need to modify code for specifying default font def copy_extensions(self, extensions): #Get pygame default font pygamedir = os.path.split(pygame.base.__file__)[0] pygame_default_font = os.path.join(pygamedir, pygame.font.get_default_font()) #Add font to list of extension to be copied extensions.append(Module("pygame.font", pygame_default_font)) py2exe.build_exe.py2exe.copy_extensions(self, extensions) class BuildExe: def __init__(self): #Name of starting .py self.script = "main.py" #Name of program self.project_name = "Around" #Project url self.project_url = "about:none" #Version of program self.project_version = "0.0.0.1" #License of the program self.license = "MyApps License" #Auhor of program self.author_name = "Keith Nemitz" self.author_email = "musenik atya hoo doh com" self.copyright = "Copyright (c) 2010 Keith Nemitz. All rights reserved." #Description self.project_description = "..." #Icon file (None will use pygame default icon) self.icon_file = None #Extra files/dirs copied to game self.extra_datas = ["data","OpenGL","extras/Microsoft.VC90.CRT.manifest", "extras/msvcm90.dll","extras/msvcp90.dll","extras/msvcr90.dll"] #Extra/excludes python modules self.extra_modules = [] self.exclude_modules = ["OpenGL"] #DLL Excludes self.exclude_dll = [''] #Zip file name (None will bundle files in exe instead of zip file) self.zipfile_name = None #Dist directory self.dist_dir ='dist' ## Code from DistUtils tutorial at http://wiki.python.org/moin/Distutils/Tutorial ## Originally borrowed from wxPython's setup and config files def opj(self, *args): path = os.path.join(*args) return os.path.normpath(path) def find_data_files(self, srcdir, *wildcards, **kw): # get a list of all files under the srcdir matching wildcards, # returned in a format to be used for install_data def walk_helper(arg, dirname, files): if '.svn' in dirname: return names = [] lst, wildcards = arg for wc in wildcards: wc_name = self.opj(dirname, wc) for f in files: filename = self.opj(dirname, f) if fnmatch.fnmatch(filename, wc_name) and not os.path.isdir(filename): names.append(filename) if names: lst.append( (dirname, names ) ) file_list = [] recursive = kw.get('recursive', True) if recursive: os.path.walk(srcdir, walk_helper, (file_list, wildcards)) else: walk_helper((file_list, wildcards), srcdir, [os.path.basename(f) for f in glob.glob(self.opj(srcdir, '*'))]) return file_list def run(self): if os.path.isdir(self.dist_dir): #Erase previous destination dir shutil.rmtree(self.dist_dir) #Use the default pygame icon, if none given if self.icon_file == None: path = os.path.split(pygame.__file__)[0] self.icon_file = os.path.join(path, 'pygame.ico') #List all data files to add extra_datas = [] for data in self.extra_datas: if os.path.isdir(data): extra_datas.extend(self.find_data_files(data, '*')) else: extra_datas.append(('.', [data])) setup( cmdclass = {'py2exe': pygame2exe}, version = self.project_version, description = self.project_description, name = self.project_name, url = self.project_url, author = self.author_name, author_email = self.author_email, license = self.license, # targets to build windows = [{ 'script': self.script, 'icon_resources': [(0, self.icon_file)], 'copyright': self.copyright }], options = {'py2exe': {'optimize': 2, 'bundle_files': 1, 'compressed': True, "includes": ["ctypes", "logging"], 'excludes': self.exclude_modules, 'packages': self.extra_modules, 'dll_excludes': self.exclude_dll} }, zipfile = self.zipfile_name, data_files = extra_datas, dist_dir = self.dist_dir ) if os.path.isdir('build'): #Clean up build dir shutil.rmtree('build') if __name__ == '__main__': if operator.lt(len(sys.argv), 2): sys.argv.append('py2exe') BuildExe().run() #Run generation raw_input("Press enter key to continue") #Pause to let user see that things ends