8 | ||
Editor: mol
Time: 2013/08/28 14:39:22 GMT+2 |
||
Note: |
changed: - Vytváření exe souborů ====================== Přestože na každém dobrém stroji je Python nainstalovaný, a pokud není, tak je často lepší ho tam nainstalovat a volat skripty zcela průhledně, tak přesto někdy může být potřeba nějaký ten exe vytvořit. *Důvody* vytváření exe mohou být různé: - od toho nejelementárnějšího: jestli to jde a jestli to já i Python zvládne, - přes komerční projekty - po skutečnou situaci, kdy dotyčný na svém stroji Python nemá a nechce. Je doporučeno *šířit scripty* a ne exe. - Je to méně objemnější, - funguje to na všech platformách, - je s tím méně práce, - podporuje se Python na stanicích - ... py2exe ......... Je ke stažení na adrese http://www.py2exe.org. Podporuje [wxPython], [Tkinter], PyGTK, [pygame] i win32com. Modul se nainstaluje standardně do adresáře site-packages. Pro Win98/Me musíte navíc ještě stáhnout Microsoft Layer for Unicode on Windows 95/98/ME Systems (unicows.dll). Je to pěkně popsáno v dokumentaci. Jednoduchý příklad ********************** Nejprve si vytvořte "pomocný" soubor setup.py ve stejném adresáři, jako je váš script:: # setup.py from distutils.core import setup import py2exe setup(console=["myscript.py"]) # setup(windows=["myscript.py"]) # pro okenní aplikace, aby nevyskakovalo černé okno Z windowsovské Příkazové řádky zavolejte: ``python setup.py py2exe``. Aby vám tento příkaz neskončil chybou dříve než začal, je třeba dodržet následující pravidla: - musíte stát ve složce s programem - tzn., že když dáte ``dir`` uvidíte kromě jiného i setup.py i váš program - v systémové proměnné PATH musí být cesta k Pythonu, vyzkoušejte tak, že zadejte příkaz ``python`` a pokud se python spustí, je vše OK, pokud ne, přidejte Pythona do `PATH </PythonInstalacePodWindows#path>`_ Po úspěšné dokončení vám vznikne, kromě jiného, adresář *dist*, ve kterém bude uloženo vše, co musíte uživateli poslat. Mezi jinými je tam i ten exe soubor. Je zde mnoho dalších voleb (jeden velký exe, okenní programy, NT služby, com servery). Popis najdete na domovské stránce http://www.py2exe.org. Důležité FAQ pro puntičkáře: Pokud přejmenujete název exe souboru, program přestane chodit! Řada lidí to přejmenovává a pak se nestačí divit a považuje to za chybu programátora. Je třeba do manuálu jasně napsat, že název exe se nesmí přejmenovat jinak program nefachá! Složitější příklad ****************** :: from distutils.core import setup import py2exe setup( name = '....', version = '1.0', description = '....', author = '...', author_email = '....', url = 'http://...', packages = ['....', '....'], windows = [{'script': '........', "icon_resources": [(1, ".........")]}], options = {'py2exe': { 'packages':'...', 'includes': '..., ...., ..., ....', 'excludes': '..., ... ,... ', "dll_excludes": '..., ,....'}}, data_files=[('bitmaps', ['....', '....']), ('config', ['....']),] ) Kromě 'console' a 'windows' existují ještě další klíčová slova a parametry. py2exe je podřízen modulu distutils, který je Pythonu standardně. Takže: 1. Ve skriptu setup.py můžete využívat všechna klíčová slova a parametry, která obsahuje distutils: http://docs.python.org/dist/simple-example.html. 2. Navíc můžete použít klíčová slova a parametry, které přidává samotný py2exe. Jejich přehled se v současnosti dá získat pouze takto :: import py2exe help(py2exe) Další příklad ************* :: from distutils.core import setup import py2exe, sys, os sys.argv.append('py2exe') setup( options = {'py2exe': {'bundle_files': 1}}, windows = [{'script': "key.py"}], zipfile = None, ) !PyInstaller ................ Žije na adrese http://pyinstaller.hpcf.upr.edu/ . Je to nástupce již nežijícího Python Installer. Vypadá jako mohutnější, s daleko více volbami. Pro začátečníky je tedy snad vhodnější py2exe. Podrobný postup je popsán v dokumentaci, takže tady jen stručně. 1. Není nutno instalovat, rozbalit archiv kamkoliv. Je dobré si k němu ještě pořídit upx: http://upx.sourceforge.net 2. Konfigurace - spustit soubor Configure.py 3. vytvoření "mezisouboru" - ``*.spec`` - Zde se nadefinují všechny možné volby pro výsledný exe: ``python Makespec.py '![OPTIONS]' script`` 4. sestavení exe - ``python Build.py specfile``, kde místo specfile zadejte jméno souboru ``*.spec``, který vám vznikl z předchozího bodu. V adresáři *distproject* vám vznikne, podobně jako u py2exe, vše včetně žádaného exe souboru. Původní script se však dá v exe nalézt v celé své kráse. Další volby je možno najít v dokumentaci, která se stáhne společně s modulem. cx_Freeze ............. Funguje pro Linux i Windows: http://starship.python.net/crew/atuining/cx_Freeze/ Autor cx_Freeze prostudoval py2exe, Python Installer a Freeze a některé jejich vlastnosti spojil do výsledného produktu. Hlavní výhodou cx_Freeze je to, že dokáže sestavit spustitelnou binárku na více systémech (Windows, UN*X, Mac) - prostě tam, kde je dostupný Python a překladač a linker C. Na druhou stranu je sestavení spustitelného programu velmi pomalé. cx_Freeze mám vyzkoušené, dokonce funguje i s velkými moduly [PyQt_PySide] a cx_Oracle (vlastně by bylo divné, že by to nefungovalo s modulem stejného autora;)) Příklad použití:: FreezePython --include-modules=cx_Oracle --target-dir=oraschemadoc-exe oraschemadoc-dev\oraschemadoc.py # anebo FreezePython --include-modules=PyQt4,sip,reportlab,datetime --target=srcdir-bin srcdir/appname.py User Account Control (UAC) .......................... Potřeba "administrátorských" oprávnění se kóduje do `manifestu`_ EXE souboru [CIT1]_, [CIT2]_, [CIT3]_. V Pythonu lze úpravu provést takto [#]_:: import win32api from xml.etree import ElementTree RESOURCE_TYPE = 24 RESOURCE_NAME = 1 RESOURCE_LANG = 1033 ASM_V1_NS = "urn:schemas-microsoft-com:asm.v1" ASM_V3_NS = "urn:schemas-microsoft-com:asm.v3" ASSEMBLY_TAG = str(ElementTree.QName(ASM_V1_NS, "assembly")) TRUST_TAG = str(ElementTree.QName(ASM_V3_NS, "trustInfo")) SECURITY_TAG = str(ElementTree.QName(ASM_V3_NS, "security")) PRIVILEGES_TAG = str(ElementTree.QName(ASM_V3_NS, "requestedPrivileges")) EXECUTION_TAG = str(ElementTree.QName(ASM_V3_NS, "requestedExecutionLevel")) LEVEL_ATTRIBUTE = "level" UI_ATTRIBUTE = "uiAccess" LEVEL_VALUES = {None: "asInvoker", False: "highestAvailable", True: "requireAdministrator"} UI_VALUES = {False: "False", True: "True"} EXECUTION_PATH = (TRUST_TAG, SECURITY_TAG, PRIVILEGES_TAG, EXECUTION_TAG) def set_uac(path, level=None, ui_access=False): """Set elevation request level of an EXE file. If the elevation is not needed, set ``level = None``. If the elevation is not necessary, set ``level = False``. If the promotion is necessary, set ``level = True``. Applications with ``ui_access == True`` must be Authenticode signed to start properly. :param path: Path to the EXE file. :type path: str :param level: Level of elevation request. :type level: bool :param ui_access: Bypass user interface control levels. :type ui_access: bool """ handle = win32api.LoadLibrary(path) manifest = win32api.LoadResource(handle, RESOURCE_TYPE, RESOURCE_NAME, RESOURCE_LANG) win32api.FreeLibrary(handle) root = ElementTree.fromstring(manifest) assert root.tag == ASSEMBLY_TAG element = get_element(root, EXECUTION_PATH) element.set(LEVEL_ATTRIBUTE, LEVEL_VALUES[level]) element.set(UI_ATTRIBUTE, UI_VALUES[ui_access]) manifest = ElementTree.tostring(root) handle = win32api.BeginUpdateResource(path, 0) win32api.UpdateResource(handle, RESOURCE_TYPE, RESOURCE_NAME, manifest, RESOURCE_LANG) win32api.EndUpdateResource(handle, 0) def get_element(root, path): """Get the element on given path (create missing elements). :param root: Root element. :type root: xml.etree.ElementTree.Element :param path: List of element names on the path. :type path: (str, ...) :return: The target element. :rtype: xml.etree.ElementTree.Element """ if not path: return root element = root.find(path[0]) if element is None: element = ElementTree.SubElement(root, path[0]) return get_element(element, path[1:]) .. [#] Tento kód funguje dobře s EXE soubory používanými ``cx_Freeze``. Může se stát, že pro jiné soubory budou potřeba jiné konstanty ``RESOURCE_TYPE``, ``RESOURCE_NAME`` a ``RESOURCE_LANG``. Zdroje ******* .. [CIT1] http://msdn.microsoft.com/en-us/library/windows/desktop/bb756929.aspx .. [CIT2] http://stackoverflow.com/questions/6166867/attach-uac-manifest-file-to-any-pe-using-update-resource .. [CIT3] http://en.wikipedia.org/wiki/User_account_control .. _manifestu: http://en.wikipedia.org/wiki/Manifest_%28.NET_Framework%29
Přestože na každém dobrém stroji je Python nainstalovaný, a pokud není, tak je často lepší ho tam nainstalovat a volat skripty zcela průhledně, tak přesto někdy může být potřeba nějaký ten exe vytvořit.
Důvody vytváření exe mohou být různé:
Je doporučeno šířit scripty a ne exe.
Je ke stažení na adrese http://www.py2exe.org. Podporuje wxPython, Tkinter, PyGTK, pygame i win32com. Modul se nainstaluje standardně do adresáře site-packages. Pro Win98/Me musíte navíc ještě stáhnout Microsoft Layer for Unicode on Windows 95/98/ME Systems (unicows.dll). Je to pěkně popsáno v dokumentaci.
Nejprve si vytvořte "pomocný" soubor setup.py ve stejném adresáři, jako je váš script:
# setup.py from distutils.core import setup import py2exe setup(console=["myscript.py"]) # setup(windows=["myscript.py"]) # pro okenní aplikace, aby nevyskakovalo černé okno
Z windowsovské Příkazové řádky zavolejte: python setup.py py2exe. Aby vám tento příkaz neskončil chybou dříve než začal, je třeba dodržet následující pravidla:
Po úspěšné dokončení vám vznikne, kromě jiného, adresář dist, ve kterém bude uloženo vše, co musíte uživateli poslat. Mezi jinými je tam i ten exe soubor. Je zde mnoho dalších voleb (jeden velký exe, okenní programy, NT služby, com servery). Popis najdete na domovské stránce http://www.py2exe.org.
Důležité FAQ pro puntičkáře: Pokud přejmenujete název exe souboru, program přestane chodit! Řada lidí to přejmenovává a pak se nestačí divit a považuje to za chybu programátora. Je třeba do manuálu jasně napsat, že název exe se nesmí přejmenovat jinak program nefachá!
from distutils.core import setup import py2exe setup( name = '....', version = '1.0', description = '....', author = '...', author_email = '....', url = 'http://...', packages = ['....', '....'], windows = [{'script': '........', "icon_resources": [(1, ".........")]}], options = {'py2exe': { 'packages':'...', 'includes': '..., ...., ..., ....', 'excludes': '..., ... ,... ', "dll_excludes": '..., ,....'}}, data_files=[('bitmaps', ['....', '....']), ('config', ['....']),] )
Kromě 'console' a 'windows' existují ještě další klíčová slova a parametry. py2exe je podřízen modulu distutils, který je Pythonu standardně. Takže:
import py2exe help(py2exe)
from distutils.core import setup import py2exe, sys, os sys.argv.append('py2exe') setup( options = {'py2exe': {'bundle_files': 1}}, windows = [{'script': "key.py"}], zipfile = None, )
Žije na adrese http://pyinstaller.hpcf.upr.edu/ . Je to nástupce již nežijícího Python Installer.
Vypadá jako mohutnější, s daleko více volbami. Pro začátečníky je tedy snad vhodnější py2exe. Podrobný postup je popsán v dokumentaci, takže tady jen stručně.
V adresáři distproject vám vznikne, podobně jako u py2exe, vše včetně žádaného exe souboru. Původní script se však dá v exe nalézt v celé své kráse. Další volby je možno najít v dokumentaci, která se stáhne společně s modulem.
Funguje pro Linux i Windows: http://starship.python.net/crew/atuining/cx_Freeze/
Autor cx_Freeze prostudoval py2exe, Python Installer a Freeze a některé jejich vlastnosti spojil do výsledného produktu. Hlavní výhodou cx_Freeze je to, že dokáže sestavit spustitelnou binárku na více systémech (Windows, UN*X, Mac) - prostě tam, kde je dostupný Python a překladač a linker C. Na druhou stranu je sestavení spustitelného programu velmi pomalé.
cx_Freeze mám vyzkoušené, dokonce funguje i s velkými moduly PyQt_PySide a cx_Oracle (vlastně by bylo divné, že by to nefungovalo s modulem stejného autora;))
Příklad použití:
FreezePython --include-modules=cx_Oracle --target-dir=oraschemadoc-exe oraschemadoc-dev\oraschemadoc.py # anebo FreezePython --include-modules=PyQt4,sip,reportlab,datetime --target=srcdir-bin srcdir/appname.py
Potřeba "administrátorských" oprávnění se kóduje do manifestu EXE souboru [CIT1], [CIT2], [CIT3]. V Pythonu lze úpravu provést takto [1]:
import win32api from xml.etree import ElementTree RESOURCE_TYPE = 24 RESOURCE_NAME = 1 RESOURCE_LANG = 1033 ASM_V1_NS = "urn:schemas-microsoft-com:asm.v1" ASM_V3_NS = "urn:schemas-microsoft-com:asm.v3" ASSEMBLY_TAG = str(ElementTree.QName(ASM_V1_NS, "assembly")) TRUST_TAG = str(ElementTree.QName(ASM_V3_NS, "trustInfo")) SECURITY_TAG = str(ElementTree.QName(ASM_V3_NS, "security")) PRIVILEGES_TAG = str(ElementTree.QName(ASM_V3_NS, "requestedPrivileges")) EXECUTION_TAG = str(ElementTree.QName(ASM_V3_NS, "requestedExecutionLevel")) LEVEL_ATTRIBUTE = "level" UI_ATTRIBUTE = "uiAccess" LEVEL_VALUES = {None: "asInvoker", False: "highestAvailable", True: "requireAdministrator"} UI_VALUES = {False: "False", True: "True"} EXECUTION_PATH = (TRUST_TAG, SECURITY_TAG, PRIVILEGES_TAG, EXECUTION_TAG) def set_uac(path, level=None, ui_access=False): """Set elevation request level of an EXE file. If the elevation is not needed, set ``level = None``. If the elevation is not necessary, set ``level = False``. If the promotion is necessary, set ``level = True``. Applications with ``ui_access == True`` must be Authenticode signed to start properly. :param path: Path to the EXE file. :type path: str :param level: Level of elevation request. :type level: bool :param ui_access: Bypass user interface control levels. :type ui_access: bool """ handle = win32api.LoadLibrary(path) manifest = win32api.LoadResource(handle, RESOURCE_TYPE, RESOURCE_NAME, RESOURCE_LANG) win32api.FreeLibrary(handle) root = ElementTree.fromstring(manifest) assert root.tag == ASSEMBLY_TAG element = get_element(root, EXECUTION_PATH) element.set(LEVEL_ATTRIBUTE, LEVEL_VALUES[level]) element.set(UI_ATTRIBUTE, UI_VALUES[ui_access]) manifest = ElementTree.tostring(root) handle = win32api.BeginUpdateResource(path, 0) win32api.UpdateResource(handle, RESOURCE_TYPE, RESOURCE_NAME, manifest, RESOURCE_LANG) win32api.EndUpdateResource(handle, 0) def get_element(root, path): """Get the element on given path (create missing elements). :param root: Root element. :type root: xml.etree.ElementTree.Element :param path: List of element names on the path. :type path: (str, ...) :return: The target element. :rtype: xml.etree.ElementTree.Element """ if not path: return root element = root.find(path[0]) if element is None: element = ElementTree.SubElement(root, path[0]) return get_element(element, path[1:])
[1] | Tento kód funguje dobře s EXE soubory používanými cx_Freeze. Může se stát, že pro jiné soubory budou potřeba jiné konstanty RESOURCE_TYPE, RESOURCE_NAME a RESOURCE_LANG. |