(unter Windows 2000)
Mit cx_Freeze kann man Python-Programme auf Computern laufen lassen auf denen kein Python installiert ist. Und das auch noch unter Windows und Linux. Natürlich muss man das Programmpaket für Linux unter Linux erstellen und das für Windows unter Windows. Aber man hat zumindest schon mal ein einziges Werkzeug für beide Betriebssysteme.
http://starship.python.net/crew/atuining/cx_Freeze/
Ziel dieser Anleitung ist es, ein Python-Program dessen GUI mit wxPython erstellt wurde, für einen Computer, auf dem kein Python und kein wxPython installiert wurde, ausführbar zu machen. So sollte dann unser Ergebnis aussehen:
Installieren von cx_Freeze
In der Anleitung steht, dass man das Binärpaket einfach in einen Ordner entpacken soll. Ich habe mich dafür entschieden, cx_Freeze unterhalb des Python-Ordners (bei mir C:\Python24) zu entpacken. Wichtig ist, dass beim Entpacken die Ordnerstruktur erhalten bleibt. cx_Freeze liegt jetzt im Ordner ``C:\Python24\cx_Freeze-3.0.2``.
Noch schnell die Versionsnummer entfernen: ``C:\Python24\cx_Freeze``
Die Ordnerstruktur sieht jetzt so aus:
Code: Alles auswählen
C:\
Python24
cx_Freeze
bases
initscripts
Start -> Einstellungen -> Systemsteuerung -> System ->
Erweitert -> Umgebungsvariablen -> Benutzervariablen
Dazu sucht man in der Liste den Namen "path", klickt auf Bearbeiten und hängt an den vorhandenen Pfad ``;C:\Python24\cx_Freeze`` an. Man beachte den Strichpunkt um den Pfad von den anderen Pfaden zu trennen.
Wenn das erledigt ist, kann man schon mal testen, ob cx_Freeze funktioniert. Einfach in die DOS-Eingabeaufforderung wechseln (Start -> Ausführen -> cmd), ``FreezePython`` eingeben und mit ENTER bestätigen. cx_Freeze sollte sich jetzt zumindest mit einer Benutzerinformation melden.
Das Beispiel
Ich habe mir dafür ein kleines Beispiel ausgedacht, das aus zwei Python-Modulen besteht. Das eine Modul liest die installierten Python-Versionen aus der Windows-Registry aus. Das andere Modul zeigt den oder die ausgelesenen Pfade in einem Fenster an.
Beide Module kommen in einen eigens dafür erstellten Projektordner. Bei mir ist das der Ordner ``C:\pythonbeispiel``.
C:\pythonbeispiel\get_pythonversions.py
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import _winreg as winreg
#----------------------------------------------------------------------
def get_python_versions():
"""
Gibt alle installierten Python-Versionen unter Windows zurück.
Dazu werden die Unterschlüssel des Registry-Schlüssels
"HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\"
ausgelesen.
"""
# Registry-Key öffnen
try:
key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Python\\PythonCore"
)
except WindowsError:
return None
try:
# Unterschlüssel durchlaufen
index = 0
versions = []
while True:
try:
keyvalue = winreg.EnumKey(key, index)
versions.append(keyvalue)
index += 1
except WindowsError:
break
finally:
# Key schließen
winreg.CloseKey(key)
# Zurück geben
return versions
def get_python_path(version = "2.4"):
"""
Gibt den Pfad zur übergebenen Pythonversion zurück.
Dazu wird der Registry-Pfad
"HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\<version>\InstallPath\"
ausgelesen.
"""
# Registry-Key öffnen
try:
key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Python\\PythonCore\\%s\\InstallPath" % version
)
except WindowsError:
return None
try:
try:
# Pfad zur Python-Installation auslesen
path = winreg.QueryValueEx(key, "")[0]
except WindowsError:
path = ""
finally:
# Schlüssel schließen
winreg.CloseKey(key)
# Zurück geben
return path
#----------------------------------------------------------------------
if __name__ == "__main__":
versions = get_python_versions()
for version in versions:
print "Python", version, "->", get_python_path(version)
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import wx
import get_pythonversions
import sys
#----------------------------------------------------------------------
class MyFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(
self, parent = None, id = -1, title = "Pythonversionen",
size = wx.Size(400, 200)
):
wx.Frame.__init__(self, parent, id, title, size = size)
# Menüleiste erstellen
menubar = wx.MenuBar()
self.SetMenuBar(menubar)
# Datei-Menü
mnu_file = wx.Menu()
menubar.Append(mnu_file, u"&Datei")
mnu_f_close = mnu_file.Append(
id = -1, text = u"Sch&ließen", help = u"Schließt dieses Fenster."
)
self.Bind(wx.EVT_MENU, self.close_frame, mnu_f_close)
# Panel erstellen und Schrift zuweisen
panel = wx.Panel(self)
font = wx.Font(
pointSize = 10,
family = wx.FONTFAMILY_SWISS,
style = wx.FONTSTYLE_NORMAL,
weight = wx.FONTWEIGHT_NORMAL,
)
panel.SetFont(font)
# Sizer vorbereiten
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox2 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(vbox2, 1, wx.EXPAND | wx.ALL, border = 2)
panel.SetSizer(vbox1)
# StaticText
label = wx.StaticText(panel, -1, " Pythonversionen")
vbox2.Add(label, flag = wx.ALL, border = 2)
# ListCtrl
listctrl = wx.ListCtrl(
panel, -1, style = wx.LC_REPORT
)
vbox2.Add(listctrl, 1, wx.EXPAND | wx.ALL, border = 2)
self.fill_listctrl(listctrl)
# Statusleiste erstellen und zuweisen
statusbar = wx.StatusBar(self)
self.SetStatusBar(statusbar)
# Ausrichten, zentrieren und anzeigen
self.Center()
self.Show()
#----------------------------------------------------------------------
def close_frame(self, event = None):
"""
Schließt dieses Fenster
"""
self.Close()
#----------------------------------------------------------------------
def fill_listctrl(self, listctrl):
"""
Füllt das Listensteuerelement mit den Python-Versionen
"""
# Spalten erstellen
listctrl.InsertColumn(0, "Version")
listctrl.InsertColumn(1, "Pfad")
# Pythonversionen auslesen
versions = get_pythonversions.get_python_versions()
# Jede Pythonversion durchlaufen, den Pfad eruieren und eintragen
if versions:
for version in versions:
path = get_pythonversions.get_python_path(version) or ""
new_index = listctrl.InsertStringItem(sys.maxint, "Python " + version)
listctrl.SetStringItem(new_index, 1, path)
# Spaltenbreiten festlegen
listctrl.SetColumnWidth(0, wx.LIST_AUTOSIZE)
listctrl.SetColumnWidth(1, wx.LIST_AUTOSIZE)
#----------------------------------------------------------------------
class MyApp(wx.App):
#----------------------------------------------------------------------
def OnInit(self):
# Frame erstellen
frame = MyFrame()
# Hier geht es erst weiter, wenn alle Fenster geschlossen wurden.
self.MainLoop()
return True
#----------------------------------------------------------------------
if __name__ == "__main__":
app = MyApp(redirect = True)
Ich erstelle mir meistens eine CMD-Datei (Stapelverarbeitungsdatei) in die ich alle Befehle schreibe, die zum Erstellen notwendig sind. So auch hier.
Die CMD-Datei kümmert sich um diese Dinge:
- Falls der Zielordner bereits existiert, wird er gelöscht.
- Der Zielordner wird erstellt.
- In den Zielordner wird die zusätzlich benötigte Datei "msvcr71.dll" opiert.
- FreezePython mit den erforderlichen Parametern starten.
C:\pythonbeispiel\make_exe_win.cmd
Code: Alles auswählen
REM --------------------------------------------------
REM Erstellt aus dem PYTHONFILE eine ausführbare EXE
REM --------------------------------------------------
SET PROJECTDIR="C:\pythonbeispiel"
SET PYTHONFILE="get_pythonversions_gui.py"
CD /D %PROJECTDIR%
RD /S /Q dist
MD dist
MD dist\win
CP %SystemRoot%\system32\msvcr71.dll dist\win\
FreezePython.exe --install-dir=dist\win --base-name=Win32GUI.exe %PYTHONFILE%
PAUSE
Üblicherweise lässt man so etwas von einem Setup-Programm wie zum Beispiel **InnoSetup** (http://www.jrsoftware.org/isinfo.php) erledigen. Dann kann man auch gleich einen Eintrag ins Startmenü erstellen lassen.
Einfaches Setup mit InnoSetup
Wenn ich schon dabei bin, dann kann ich auch noch schnell ein Setup dafür erstellen.
InnoSetup erhält man über die Website http://www.jrsoftware.org/isinfo.php.
Sobald man InnoSetup startet, fragt einen der Assistent nach den wichtigsten Informationen die InnoSetup braucht. Danach lässt man InnoSetup das Setup generieren.
Hier ein Beispiel, wie ich es eingestellt habe.
C:\pythonbeispiel\innosetup.iss
Keine Angst, diese Informationen sammelt alle der Assistent. Man muss bei so kleinen Programmen selten etwas an den Einstellungen verändern.; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
[Setup]
AppName=Get Python Versions
AppVerName=Get Python Versions 0.1
AppPublisher=Gerolds Penz
DefaultDirName={pf}\get_python_versions
DefaultGroupName=Get Python Versions
AllowNoIcons=yes
OutputDir=C:\pythonbeispiel\setup\win
OutputBaseFilename=get_python_versions_setup
Compression=lzma
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "C:\pythonbeispiel\dist\win\get_pythonversions_gui.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\pythonbeispiel\dist\win\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\Get Python Versions"; Filename: "{app}\get_pythonversions_gui.exe"
Name: "{group}\{cm:UninstallProgram,Get Python Versions}"; Filename: "{uninstallexe}"
Name: "{userdesktop}\Get Python Versions"; Filename: "{app}\get_pythonversions_gui.exe"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Get Python Versions"; Filename: "{app}\get_pythonversions_gui.exe"; Tasks: quicklaunchicon
[Run]
Filename: "{app}\get_pythonversions_gui.exe"; Description: "{cm:LaunchProgram,Get Python Versions}"; Flags: nowait postinstall skipifsilent
So, dass war´s fürs Erste. Viel Spaß beim Nachmachen.
lg
Gerold
Edit: sys.maxint hinzugefügt