I'm trying to make an exe by py2exe. The program is showing a popup-like window using Tkinter. The problem is, everything works fine when I run the setup like this:
setup(windows = [{'script': "msg.py"}], zipfile = None)
but it fails when I try to make an one-file exe:
setup(windows = [{'script': "msg.py"}], zipfile = None, options = {'py2exe': {'bundle_files': 1, 'compressed': True}})
Actually the final exe runs without problems, but it doesn't display any window. I've read there may be problems with bundle_files=1 at Windows 7, but I also tried bundle_files=2 with the same effect.
Here is my msg.py script:
from win32gui import FindWindow, SetForegroundWindow
from Image import open as iopen
from ImageTk import PhotoImage
from Tkinter import Tk, Label
from threading import Timer
from subprocess import Popen
import os
def Thread(t, fun, arg=None):
if arg<>None: x = Timer(t, fun, arg)
else: x = Timer(t, fun)
x.daemon = True
x.start()
def NewMessage():
global root
if not os.path.exists('dane/MSG'):
open('dane/MSG', 'w').write('')
root = Tk()
img = PhotoImage(iopen("incl/nowa.png"))
label = Label(root, image=img)
label.image = img
label.bind("<Button-1>", Click)
label.pack()
root.geometry('-0-40')
root.wm_attributes("-topmost", 1)
root.overrideredirect(1)
root.mainloop()
def Click(event):
global root, exit
root.destroy()
os.remove('dane/MSG')
OpenApp()
exit = True
def OpenApp():
hwnd = FindWindow(None, 'My program name')
if hwnd: SetForegroundWindow(hwnd)
else: Popen('app.exe')
root, exit = None, False
NewMessage()
Any ideas? I've read there are some problems with Tkinter, but there were about compilation. My script is compiled and it doesn't throw any exceptions, but doesn't show the window...
I ended up encountering this same issue, my solution involved doing the following:
Add
"dll_excludes": ["tcl85.dll", "tk85.dll"],
in your options = {...}
and then manually copy those two DLLs from
PYTHON_PATH\DLLs\ (in my case C:\Python27\DLLs)
to the location of your exe and try running it.
An alternative to dll_excludes and manual copying is to patch py2exe to know these files have to be placed directly in the dist directory.
Inside build_exe.py, there's a class called py2exe, which contains a list dlls_in_exedir for dll that have to go there. This list is set during a function named plat_prepare, and you can add the tclXX.dll and tkXX.dll files to it to make sure they are copied correctly.
Of course, unless you're the only one who will ever build this, you don't necessarily know which Tcl and Tk version you need to bundle - someone might have built their Python themselves, or are using an older Python with older DLLs. Therefore, you'll need to check which versions the system is actually using. py2exe actually already does this in a different place: by importing the internal _tkinter module (the actual Tk interface, usually a DLL) and accessing TK_VERSION and TCL_VERSION, which you can then use to generate and add the correct filenames.
If others are supposed to build your application, you probably don't want to make them modify their py2exe install, so here's how you can monkeypatch it from your setup.py:
import py2exe
py2exe.build_exe.py2exe.old_prepare = py2exe.build_exe.py2exe.plat_prepare
def new_prep(self):
self.old_prepare()
from _tkinter import TK_VERSION, TCL_VERSION
self.dlls_in_exedir.append('tcl{0}.dll'.format(TCL_VERSION.replace('.','')))
self.dlls_in_exedir.append('tk{0}.dll'.format(TK_VERSION.replace('.','')))
py2exe.build_exe.py2exe.plat_prepare = new_prep
This even works with bundle_files=1 on Windows 7.
If you have only one version the you can copy files with
via data_file. Below a full example:
WinXP
Python2.7.6
tk8.5
tcl8.5
tix8.4.3
py2exe 0.6.9
foo.py:
# -*- coding: iso-8859-1 -*-
import Tkinter
"""
sets TCL_LIBRARY, TIX_LIBRARY and TK_LIBRARY - see installation Lib\lib-tk\FixTk.py
"""
Tkinter._test()
Setup.py :
# -*- coding: iso-8859-1 -*-
from distutils.core import setup
import py2exe
import sys
import os
import os.path
sys.argv.append ('py2exe')
setup (
options =
{'py2exe':
{ "bundle_files" : 1 # 3 = don't bundle (default)
# 2 = bundle everything but the Python interpreter
# 1 = bundle everything, including the Python interpreter
, "compressed" : False # (boolean) create a compressed zipfile
, "unbuffered" : False # if true, use unbuffered binary stdout and stderr
, "includes" :
[ "Tkinter", "Tkconstants"
]
, "excludes" : ["tcl", ]
, "optimize" : 0 #-O
, "packages" :
[
]
, "dist_dir" : "foo"
, "dll_excludes": ["tcl85.dll", "tk85.dll"]
,
}
}
, windows =
["foo.py"
]
, zipfile = None
# the syntax for data files is a list of tuples with (dest_dir, [sourcefiles])
# if only [sourcefiles] then they are copied to dist_dir
, data_files = [ os.path.join (sys.prefix, "DLLs", f)
for f in os.listdir (os.path.join (sys.prefix, "DLLs"))
if ( f.lower ().startswith (("tcl", "tk"))
and f.lower ().endswith ((".dll", ))
)
]
,
)
Related
I'm having a python project and use git as version control software.
The software will be deployed using Cx_Freeze.
I would like to display the version and author (and possibly other metadata) captured during the build process (freezing the script) within an About dialogue in my Application.
This is an example of the setup script:
import sys
import subprocess
from cx_Freeze import setup, Executable
build_exe_options = {}
base = "Win32GUI"
version = subprocess.run(['git', 'describe', '--abbrev=4', '--dirty', '--always', '--tags'],
capture_output=True, encoding='utf-8').stdout.strip()
setup(
name="XY",
version=version,
author="My Name",
description="Mysterious GUI application",
options={"build_exe": build_exe_options},
executables=[Executable("XY.py", base=base)],
)
Simple example of an About dialogue:
from tkinter import messagebox
def on_about():
messagebox.showinfo(f'About', 'Software XY, written by {author}, version {version}')
# Should display e.g. 'Software XY, written by My Name, version 4b06-dirty'
Does anyone know if this is possible and how to achieve this?
Thanks to all in advance!
I came up with a first solution where I create a sub-module within the main package of my application when the setup script is being executed. I import the __version__ variable into the __init__.py of that package only when its frozen and if the sub-module exists:
setup.py:
import subprocess
import os.path
import mymodule
from cx_Freeze import setup, Executable
def create_versionmodule(packagepath: str):
"""
creates a file packagepath/_version.py which defines a __version__ variable
which contains the stripped output of "git describe --dirty --always --tags"
"""
version = subprocess.run(['git', 'describe', '--dirty', '--always', '--tags'],
capture_output=True, encoding='utf-8').stdout.strip()
with open(os.path.join(packagepath, '_version.py'), mode='w', encoding='utf-8') as file:
file.write(f'__version__: str = {version!r}\n')
build_exe_options = {}
base = "Win32GUI"
create_versionmodule(packagepath=os.path.dirname(mymodule.__file__))
setup(
name="XY",
description="Mysterious GUI application",
options={"build_exe": build_exe_options},
executables=[Executable("XY.py", base=base)],
)
mymodule/__init__.py:
import sys as _sys
__version__ = 'UNKNOWN'
if getattr(_sys, "frozen", False):
try:
from mymodule._version import __version__
except ModuleNotFoundError:
pass
Now I can access the version variable from everywhere in my code:
import mymodule
from tkinter import messagebox
def on_about():
messagebox.showinfo(f'About', 'Software XY, version {mymodule.__version__}')
I made small game in pygame and python 2.7 and added submit box with Tkinter.
It worked fine till I compiled it with py2exe / pygame2exe.
Compilation was error-free.
But when i clicked on exe file to launch the application, compiled-code threw this error:
fatal python error (pygame parachute) Segmentation Fault
This application has terminated in unusal way for more
information contact application support team.
When I delete Tkinter code and compile it it runs fine.
This is a part of Tkinter code:
#i tried importing both with import Tkinter and from Tkinter import*
if event.key==pygame.K_s:
subbox=Tkinter.Tk()
subbox_label=Tkinter.Label(subbox,text="Type your name:")
subbox_label.pack()
subbox_entry=Tkinter.Entry(subbox)
subbox_entry.pack()
def savescore(a):
a=str(a)
print a
print subbox_entry.get()
player_name=subbox_entry.get()
player_score=a
subbox_button=Tkinter.Button(text="Click",command=lambda:savescore(score))
subbox_button.pack()
subbox.mainloop()
UPDATE:
I kicked out Tkinter code line by line and it came up that importing Tkinter causes error!
That means that if I have just:
import Tkinter
my game won't work!!! What should I do?
setup file(pygame2exe but I may accidently delete something inside):
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 which fixes the pygame mixer and pygame font
origIsSystemDLL = py2exe.build_exe.isSystemDLL # save the orginal before we edit it
def isSystemDLL(pathname):
# checks if the freetype and ogg dll files are being included
if os.path.basename(pathname).lower() in ("libfreetype-6.dll", "libogg-0.dll","sdl_ttf.dll"): # "sdl_ttf.dll" added by arit.
return 0
return origIsSystemDLL(pathname) # return the orginal function
py2exe.build_exe.isSystemDLL = isSystemDLL # override the default function with this one
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 = "game_0.3.py"
#Name of program
self.project_name = "game"
#Project url
self.project_url = "it will be on sourceforge and indieDB"
#Version of program
self.project_version = "0.3"
#License of the program
self.license = "gnu gpl 2.0"
#Auhor of program
self.author_name = "John Doe "
self.author_email = "i dont want spam"
self.copyright = "John Doe 2014"
#Description
self.project_description = None
#Icon file (None will use pygame default icon)
self.icon_file = "icon.ico"
#Extra files/dirs copied to game
self.extra_datas = ["block.png","CHARACTER.png","icon.ico","COPYING.txt","README1.txt","name.txt","score.txt"]
#Extra/excludes python modules
self.extra_modules = []
self.exclude_modules =['AppKit', 'Foundation', 'Numeric', 'OpenGL.GL', '_scproxy', '_sysconfigdata', 'copyreg', 'dummy.Process', 'numpy', 'pkg_resources', 'queue', 'winreg', 'pygame.sdlmain_osx']
#DLL Excludes
self.exclude_dll = ['']
#python scripts (strings) to be included, seperated by a comma
self.extra_scripts = []
#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
console = [{
'script': self.script,
'icon_resources': [(0, self.icon_file)],
'copyright': self.copyright
}],
options = {'py2exe': {'optimize': 2, 'bundle_files': 1, 'compressed': True, \
'excludes': self.exclude_modules, 'packages': self.extra_modules, \
'dll_excludes': self.exclude_dll,
'includes': self.extra_scripts} },
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 any key to continue") #Pause to let user see that things ends
another important thing:if i import Tkinter before pygame there is no segmentation error but game doesn't run and error window pops out and says this application requested runtime to terminate in unusal way for more information contact app support
Did you check py2exe/Bugs?
While it is not exactly the same crash, the root-cause, related to Tkinter internal dependence on sub-layer of Tcl & Tk DLL services seems similar:
cit.:
"""
Using Tkinter, and bundle_files = 1, i get an immediate crash.
Here's my setup:
winxp sp2
py2exe 0.6.8
python 2.5.1
My test file is "example.py", as follows:
#### start
from Tkinter import *
if __name__ == '__main__':
print "hello"
#### end
my setup.py is as follows:
#### start
from distutils.core import setup
import py2exe
setup(
options = {'py2exe': {'bundle_files': 1}},
zipfile = None,
console=['example.py'])
#### end
it compiles just fine, but when running the "example.exe" that is produced in the "dist" directory, it immediately gets the error message "example.exe has encountered a problem and needs to close. We are sorry for the inconvenience".
Using the same setup.py, but with bundle_files = 3 works fine; using bundle_files = 2 causes the same crash.
I hope this is sufficient information to replicate this bug. I will be happy to provide any other info if you need it - just post back here.
"""
+ a there proposed workaround:
cit.:
"""
I "fixed" this by editing site-packages/py2exe/build_exe.py,
adding "tcl85.dll" and"tk85.dll" to the "dlls_in_exedir" list
-- meaning that they get put next to the .exe rather than bundled inside it.
Slightly messy, but much better than bundled=3
"""
I want to create a start menu or Desktop shortcut for my Python windows installer package. I am trying to follow https://docs.python.org/3.4/distutils/builtdist.html#the-postinstallation-script
Here is my script;
import sys
from os.path import dirname, join, expanduser
pyw_executable = sys.executable.replace('python.exe','pythonw.exe')
script_file = join(dirname(pyw_executable), 'Scripts', 'tklsystem-script.py')
w_dir = expanduser(join('~','lsf_files'))
print(sys.argv)
if sys.argv[1] == '-install':
print('Creating Shortcut')
create_shortcut(
target=pyw_executable,
description='A program to work with L-System Equations',
filename='L-System Tool',
arguments=script_file,
workdir=wdir
)
I also specified this script in scripts setup option, as indicated by aforementioned docs.
Here is the command I use to create my installer;
python setup.py bdist_wininst --install-script tklsystem-post-install.py
After I install my package using created windows installer, I can't find where my shorcut is created, nor I can confirm whether my script run or not?
How can I make setuptools generated windows installer to create desktop or start menu shortcuts?
Like others have commented here and elsewhere the support functions don't seem to work at all (at least not with setuptools). After a good day's worth of searching through various resources I found a way to create at least the Desktop shortcut. I'm sharing my solution (basically an amalgam of code I found here and here). I should add that my case is slightly different from yasar's, because it creates a shortcut to an installed package (i.e. an .exe file in Python's Scripts directory) instead of a script.
In short, I added a post_install function to my setup.py, and then used the Python extensions for Windows to create the shortcut. The location of the Desktop folder is read from the Windows registry (there are other methods for this, but they can be unreliable if the Desktop is at a non-standard location).
#!/usr/bin/env python
import os
import sys
import sysconfig
if sys.platform == 'win32':
from win32com.client import Dispatch
import winreg
def get_reg(name,path):
# Read variable from Windows Registry
# From https://stackoverflow.com/a/35286642
try:
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
winreg.KEY_READ)
value, regtype = winreg.QueryValueEx(registry_key, name)
winreg.CloseKey(registry_key)
return value
except WindowsError:
return None
def post_install():
# Creates a Desktop shortcut to the installed software
# Package name
packageName = 'mypackage'
# Scripts directory (location of launcher script)
scriptsDir = sysconfig.get_path('scripts')
# Target of shortcut
target = os.path.join(scriptsDir, packageName + '.exe')
# Name of link file
linkName = packageName + '.lnk'
# Read location of Windows desktop folder from registry
regName = 'Desktop'
regPath = r'Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
desktopFolder = os.path.normpath(get_reg(regName,regPath))
# Path to location of link file
pathLink = os.path.join(desktopFolder, linkName)
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(pathLink)
shortcut.Targetpath = target
shortcut.WorkingDirectory = scriptsDir
shortcut.IconLocation = target
shortcut.save()
setup(name='mypackage',
...,
...)
if sys.argv[1] == 'install' and sys.platform == 'win32':
post_install()
Here's a link to a full setup script in which I used this:
https://github.com/KBNLresearch/iromlab/blob/master/setup.py
If you want to confirm whether the script is running or not, you can print to a file instead of the console. Looks like text you print to console in the post-install script won't show up.
Try this:
import sys
from os.path import expanduser, join
pyw_executable = join(sys.prefix, "pythonw.exe")
shortcut_filename = "L-System Toolsss.lnk"
working_dir = expanduser(join('~','lsf_files'))
script_path = join(sys.prefix, "Scripts", "tklsystem-script.py")
if sys.argv[1] == '-install':
# Log output to a file (for test)
f = open(r"C:\test.txt",'w')
print('Creating Shortcut', file=f)
# Get paths to the desktop and start menu
desktop_path = get_special_folder_path("CSIDL_COMMON_DESKTOPDIRECTORY")
startmenu_path = get_special_folder_path("CSIDL_COMMON_STARTMENU")
# Create shortcuts.
for path in [desktop_path, startmenu_path]:
create_shortcut(pyw_executable,
"A program to work with L-System Equations",
join(path, shortcut_filename),
script_path,
working_dir)
At least with Python 3.6.5, 32bit on Windows, setuptools does work for this. But based on the accepted answer, by trial and error I found some issues that may have caused your script to fail to do what you wanted.
create_shortcut does not accept keyword arguments, only positional, so its usage in your code is invalid
You must add a .lnk extension for Windows to recognise the shortcut
I found sys.executable will be the name of the installer executable, not the python executable
As mentioned, you can't see stdout or stderr so you might want to log to a text file. I would suggest also redirecting sys.stdout and sys.stderr to the log file.
(Maybe not relevant) as mentioned in this question there appears to be a bug with the version string generated by bdist_wininst. I used the hexediting hack from an answer there to work around this. The location in the answer is not the same, you have to find the -32 yourself.
Full example script:
import sys
import os
import datetime
global datadir
datadir = os.path.join(get_special_folder_path("CSIDL_APPDATA"), "mymodule")
def main(argv):
if "-install" in argv:
desktop = get_special_folder_path("CSIDL_DESKTOPDIRECTORY")
print("Desktop path: %s" % repr(desktop))
if not os.path.exists(datadir):
os.makedirs(datadir)
dir_created(datadir)
print("Created data directory: %s" % repr(datadir))
else:
print("Data directory already existed at %s" % repr(datadir))
shortcut = os.path.join(desktop, "MyModule.lnk")
if os.path.exists(shortcut):
print("Remove existing shortcut at %s" % repr(shortcut))
os.unlink(shortcut)
print("Creating shortcut at %s...\n" % shortcut)
create_shortcut(
r'C:\Python36\python.exe',
"MyModuleScript",
shortcut,
"",
datadir)
file_created(shortcut)
print("Successfull!")
elif "-remove" in sys.argv:
print("Removing...")
pass
if __name__ == "__main__":
logfile = r'C:\mymodule_install.log' # Fallback location
if os.path.exists(datadir):
logfile = os.path.join(datadir, "install.log")
elif os.environ.get("TEMP") and os.path.exists(os.environ.get("TEMP"),""):
logfile = os.path.join(os.environ.get("TEMP"), "mymodule_install.log")
with open(logfile, 'a+') as f:
f.write("Opened\r\n")
f.write("Ran %s %s at %s" % (sys.executable, " ".join(sys.argv), datetime.datetime.now().isoformat()))
sys.stdout = f
sys.stderr = f
try:
main(sys.argv)
except Exception as e:
raise
f.close()
sys.exit(0)
UPD: on an off chance that the client machine has pywin32 installed, we try in-process creation first. Somewhat cleaner that way.
Here is another take. This assumes the package is called myapp, and that also becomes the executable that you want a shortcut to. Substitute your own package name and your own shortcut text.
Uses a Windows Scripting Host COM class - in process if possible, inside a Powershell command line as a subprocess if not. Tested on Python 3.6+.
from setuptools import setup
from setuptools.command.install import install
import platform, sys, os, site
from os import path, environ
def create_shortcut_under(root, exepath):
# Root is an env variable name -
# either ALLUSERSPROFILE for the all users' Start menu,
# or APPDATA for the current user specific one
profile = environ[root]
linkpath = path.join(profile, "Microsoft", "Windows", "Start Menu", "Programs", "My Python app.lnk")
try:
from win32com.client import Dispatch
from pywintypes import com_error
try:
sh = Dispatch('WScript.Shell')
link = sh.CreateShortcut(linkpath)
link.TargetPath = exepath
link.Save()
return True
except com_error:
return False
except ImportError:
import subprocess
s = "$s=(New-Object -COM WScript.Shell).CreateShortcut('" + linkpath + "');$s.TargetPath='" + exepath + "';$s.Save()"
return subprocess.call(['powershell', s], stdout = subprocess.DEVNULL, stderr = subprocess.DEVNULL) == 0
def create_shortcut(inst):
try:
exepath = path.join(path.dirname(sys.executable), "Scripts", "myapp.exe")
if not path.exists(exepath):
# Support for "pip install --user"
exepath = path.join(path.dirname(site.getusersitepackages()), "Scripts", "myapp.exe")
# If can't modify the global menu, fall back to the
# current user's one
if not create_shortcut_under('ALLUSERSPROFILE', exepath):
create_shortcut_under('APPDATA', exepath)
except:
pass
class my_install(install):
def run(self):
install.run(self)
if platform.system() == 'Windows':
create_shortcut(self)
#...
setup(
#...
cmdclass={'install': my_install},
entry_points={"gui_scripts": ["myapp = myapp.__main__:main"]},
EDIT: Turns out the actual error was with the font code - Apparently I had to use
pygame.font.SysFont("some_font", font_size)
instead of
pygame.font.Font(None, font_size)
everywhere in my original piece of code.
Consider this question resolved.
I've made a game with pygame and want it to run on computers without Python and Pygame, for which matter I got py2exe and shamelessly copied the pygame2exe code found here, adjusting it for my file's name and that kind of stuff...
The conversion (I tried both the windows cmd thingy and actual Python, both with the same results) was successful, and when I run the executable file I get a black window without the actual background, the only thing I saw that it worked were the icon and title of the window which were integrated in the Python code. Afterwards I immediately get this error message:
Runtime error! This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
Since the icon was displayed at the top left of the window (which it also has to load an image for) and the background didn't appear, the error was most likely somewhere in between the following few lines, if it's due to some problem in the actual code (although it works in IDLE). There I do the following things:
Defining variables for images, then defining another variable as that variable so it's a copy of it, so the game works faster
Loading sound effects and setting their volume
Setting background music, it's volume and making it on loop
Following that, these are the lines of code up until the setting of the background image.
running = True
game = 0
clock = pygame.time.Clock()
FPS = 150
name = ""
while running==True:
screen.fill(0)
clock.tick(FPS)
for x in range(width/background.get_width()+1):
for y in range(height/background.get_height()+1):
screen.blit(background,(x*200,y*200))
For reference, this is the code of setup.py (although I doubt that's the problem anyway:
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 which fixes the pygame mixer and pygame font
origIsSystemDLL = py2exe.build_exe.isSystemDLL # save the orginal before we edit it
def isSystemDLL(pathname):
# checks if the freetype and ogg dll files are being included
if os.path.basename(pathname).lower() in ("libfreetype-6.dll", "libogg- 0.dll","sdl_ttf.dll"): # "sdl_ttf.dll" added by arit.
return 0
return origIsSystemDLL(pathname) # return the orginal function
py2exe.build_exe.isSystemDLL = isSystemDLL # override the default function with this one
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 = "test.py"
#Name of program
self.project_name = "test"
#Project url
self.project_url = "about:none"
#Version of program
self.project_version = "0.9"
#License of the program
self.license = "No license"
#Auhor of program
self.author_name = "Me"
self.author_email = "example#example.com"
self.copyright = "Copyright (c) 2009 Me."
#Description
self.project_description = "Test"
#Icon file (None will use pygame default icon)
self.icon_file = None
#Extra files/dirs copied to game
self.extra_datas = ["spiel"]
#Extra/excludes python modules
self.extra_modules = []
self.exclude_modules = []
#DLL Excludes
self.exclude_dll = ['']
#python scripts (strings) to be included, seperated by a comma
self.extra_scripts = []
#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, \
'excludes': self.exclude_modules, 'packages': self.extra_modules, \
'dll_excludes': self.exclude_dll,
'includes': self.extra_scripts} },
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 any key to continue") #Pause to let user see that things ends
Further information:
OS: Windows 7, 32 bit
Pygame version: 1.9.2. (I think - it's the latest version)
Python version: 2.7.6.
Py2exe version: Whatever the latest one was
I never actually had a msvcr90.dll file version 9.0.21022.8, like the py2exe tutorial specifically recommends to use. I now have msvcr71.dll, msvcr100.dll, msvcr100_clr0400.dll and msvcr110_clr0400.dll (intended for this OS) instead, which was what seemed to be available from microsoft packages. Is it possible that represents the problem? If so, where the hell can I get the correct file from? I tried looking it up, but there didn't seem to be any download link for it (at least not that it gives me the exact file I want now).
And if not, do you know where else the problem could be?
msvcr90.dll comes along with Microsoft Visual C++ 2008 runtimes. Grab the version for your architecture, install and try again. Here is the x86 version and here is the x64 version.
Platform is Windows 7 64bit using python 2.7 and GTK3+ installed from http://sourceforge.net/projects/pygobjectwin32/files/?source=navbar
The exe is compiled but fails to run, due to this
The following modules appear to be missing
['gi.repository.Gdk', 'gi.repository.Gtk', 'overrides.registry']
How can i properly include these files?
imports in my .py file
from gi.repository import Gtk, Gdk
my setup file
#!/usr/bin/env python
from distutils.core import setup
import py2exe, sys
sys.path.append("C:\Python27\Lib\site-packages\gnome")
sys.path.append("C:\Python27\Lib\site-packages\repository")#tried including these extra dirs
sys.path.append("C:\Python27\Lib\site-packages\override")#tried including these extra dirs
sys.path.append("C:\Python27\Lib\site-packages\gi") #tried including these extra dirs
setup(
options = {
'py2exe': {
'bundle_files': 1,
#this does not work 'includes': ['Gtk']
}
},
console=["gui.py"],
zipfile=None
)
The executable error when ran:
ImportError: MemoryLoadLibrary failed loading gi\_gi.pyd
Thanks
You need to add "gi" to "packages".
'options': {
'py2exe': {
'packages': 'gi',
}
}
I haven't tested it on 64bit but this is the setup.py I've used to build with cx_freeze, py2exe looks like is not maintained for a long time.
from cx_Freeze import setup, Executable
import os, site, sys
## Get the site-package folder, not everybody will install
## Python into C:\PythonXX
site_dir = site.getsitepackages()[1]
include_dll_path = os.path.join(site_dir, "gtk")
## Collect the list of missing dll when cx_freeze builds the app
missing_dll = ['libgtk-3-0.dll',
'libgdk-3-0.dll',
'libatk-1.0-0.dll',
'libcairo-gobject-2.dll',
'libgdk_pixbuf-2.0-0.dll',
'libjpeg-8.dll',
'libpango-1.0-0.dll',
'libpangocairo-1.0-0.dll',
'libpangoft2-1.0-0.dll',
'libpangowin32-1.0-0.dll',
'libgnutls-26.dll',
'libgcrypt-11.dll',
'libp11-kit-0.dll'
]
## We also need to add the glade folder, cx_freeze will walk
## into it and copy all the necessary files
glade_folder = 'glade'
## We need to add all the libraries too (for themes, etc..)
gtk_libs = ['etc', 'lib', 'share']
## Create the list of includes as cx_freeze likes
include_files = []
for dll in missing_dll:
include_files.append((os.path.join(include_dll_path, dll), dll))
## Let's add glade folder and files
include_files.append((glade_folder, glade_folder))
## Let's add gtk libraries folders and files
for lib in gtk_libs:
include_files.append((os.path.join(include_dll_path, lib), lib))
base = None
## Lets not open the console while running the app
if sys.platform == "win32":
base = "Win32GUI"
executables = [
Executable("main.py",
base=base
)
]
buildOptions = dict(
compressed = False,
includes = ["gi"],
packages = ["gi"],
include_files = include_files
)
setup(
name = "test_gtk3_app",
author = "Gian Mario Tagliaretti",
version = "1.0",
description = "GTK 3 test",
options = dict(build_exe = buildOptions),
executables = executables
)
Depending on the libraries you have used you might have to add some missing dll, look at the output of cx_freeze.
I've posted the same some time ago on gnome's wiki:
https://wiki.gnome.org/Projects/PyGObject#Building_on_Win32_with_cx_freeze