py2exe - génère un fichier exécutable unique


141

Je pensais avoir entendu dire que py2exe était capable de le faire, mais je ne l'ai jamais compris. Quelqu'un a-t-il réussi cela? Puis-je voir votre fichier setup.py et les options de ligne de commande que vous avez utilisées?

Fondamentalement, j'y pense en me donnant un seul fichier exécutable qui fait quelque chose comme se décompresser dans peut-être / temp et s'exécute.


Cela s'applique-t-il à Python 3 ou aux versions postérieures à Python 2?
Vincent

Réponses:


105

PyInstaller créera un seul fichier .exe sans dépendances; utilisez l' --onefileoption. Il le fait en emballant toutes les bibliothèques partagées nécessaires dans l'exécutable et en les décompressant avant son exécution, comme vous le décrivez (EDIT: py2exe a également cette fonctionnalité, voir la réponse de minty )

J'utilise la version de PyInstaller de svn, car la dernière version (1.3) est quelque peu obsolète. Cela fonctionne très bien pour une application qui dépend de PyQt, PyQwt, numpy, scipy et quelques autres.


5
J'ai trouvé que py2exe fonctionnait beaucoup mieux que pyInstaller, lorsque vous utilisez des œufs. La réponse de minty est la solution.
gbjbaanb

Veuillez noter qu'à partir de la version 1.4, PyInstaller ne prend pas en charge Python 2.6+ sur Windows
Joril

2
J'utilise maintenant la version 1.5.1, et cela fonctionne avec Python 2.7.2.
oob

1
py2exe peut créer un fichier exécutable unique si vous spécifiez quelques arguments dans le programme du compilateur. py2exe a un tutoriel pour les exécutables de fichier unique en ligne.
trevorKirk du

2
Objectif de point de vue: Je ne vois pas en quoi c'est une réponse acceptable car elle n'aborde pas la question de la création d'un seul fichier exe avec py2exe. (Néanmoins, c'est une réponse utile bien sûr.)
Jonathan Komar

171

La façon de faire cela en utilisant py2exe est d'utiliser l'option bundle_files dans votre fichier setup.py. Pour un seul fichier, vous voudrez définir bundle_filessur 1, compressedsur True et définir l'option zipfile sur Aucun. De cette façon, il crée un fichier compressé pour une distribution facile.

Voici une description plus complète de l'option bundle_file citée directement depuis le site py2exe *

Utilisation de "bundle_files" et "zipfile"

Un moyen plus simple (et meilleur) de créer des exécutables à un seul fichier est de définir bundle_files sur 1 ou 2, et de définir zipfile sur None. Cette approche ne nécessite pas l'extraction de fichiers vers un emplacement temporaire, ce qui permet un démarrage du programme beaucoup plus rapide.

Les valeurs valides pour bundle_files sont:

  • 3 (par défaut) ne pas grouper
  • 2 bundle tout sauf l'interpréteur Python
  • 1 bundle tout, y compris l'interpréteur Python

Si zipfile est défini sur None, les fichiers seront regroupés dans l'exécutable au lieu de library.zip.

Voici un exemple de 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,
)

5
Bien sûr, si vous voulez que seul l'interpréteur ne soit pas fourni, choisissez 2 pour l'option bundle_files. Bonne chance!
minty

13
Veuillez noter que bundle_files 1 n'est pas pris en charge sur amd64 (py2exe 0.6.9 pour Python 2.6 au moins)
Joril

2
@Pat: L'appel pour exécuter py2exe est "python setup.py py2exe". En ajoutant automatiquement le "py2exe" à la fin, cela signifie simplement que vous n'avez pas à le taper sur la ligne de commande.
orlade

2
Pas exactement un seul exécutable, que vous devez installer la DLL d'exécution Microsoft Visual C .
Kevin Smyth

2
J'avais une application console que je voulais avoir comme exécutable unique. J'ai dû remplacer windows = [{'script': "single.py"}]par console = ['single.py']un double-clic sur le fichier pour ouvrir une fenêtre CMD sous Windows.
Jeff B le

13

Comme le mentionne l'autre poster, py2exe générera un exécutable + quelques bibliothèques à charger. Vous pouvez également avoir des données à ajouter à votre programme.

L'étape suivante consiste à utiliser un installateur, pour regrouper tout cela dans un programme installable / non-installable facile à utiliser.

J'utilise InnoSetup ( http://www.jrsoftware.org/isinfo.php ) avec plaisir depuis plusieurs années et pour des programmes commerciaux, je le recommande donc vivement.


+1 pour indiquer qu'après py2exe, il y a encore des choses à emballer.
joaquin

6

J'ai pu créer un seul fichier exe avec toutes les ressources intégrées dans l'exe. Je construis sur des fenêtres. donc cela expliquera certains des appels os.system que j'utilise.

J'ai d'abord essayé de convertir toutes mes images en bitmats, puis tous mes fichiers de données en chaînes de texte. mais cela a rendu l'exe final très très grand.

Après avoir effectué une recherche sur Google pendant une semaine, j'ai trouvé comment modifier le script py2exe pour répondre à mes besoins.

voici le lien du patch sur sourceforge que j'ai soumis, veuillez poster des commentaires afin que nous puissions l'inclure dans la prochaine distribution.

http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583

cela explique toutes les modifications apportées, j'ai simplement ajouté une nouvelle option à la ligne de configuration. voici mon setup.py.

je vais essayer de le commenter du mieux que je peux. Sachez que mon setup.py est complexe en raison du fait que j'accède aux images par nom de fichier. je dois donc stocker une liste pour en garder une trace.

il s'agit d'un économiseur d'écran que j'essayais de créer.

J'utilise exec pour générer ma configuration au moment de l'exécution, il est plus facile de couper et coller comme ça.

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])

panne

script = py script je veux me tourner vers un exe

icon_resources = l'icône de l'exe

file_resources = fichiers que je souhaite intégrer dans l'exe

other_resources = une chaîne à intégrer dans l'exe, dans ce cas une liste de fichiers.

options = py2exe options pour tout créer dans un seul fichier exe

bitmap_strings = une liste de fichiers à inclure

Veuillez noter que file_resources n'est pas une option valide tant que vous ne modifiez pas votre fichier py2exe.py comme décrit dans le lien ci-dessus.

première fois que j'ai essayé de publier du code sur ce site, si je me trompe, ne m'enflammez pas.

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, c'est tout pour le setup.py maintenant la magie avait besoin d'accéder aux images. J'ai développé cette application sans py2exe en tête, puis je l'ai ajoutée plus tard. vous verrez donc l'accès pour les deux situations. si le dossier d'images ne peut pas être trouvé, il essaie d'extraire les images des ressources exe. le code l'expliquera. cela fait partie de ma classe de sprite et utilise un directx. mais vous pouvez utiliser n'importe quelle API que vous voulez ou simplement accéder aux données brutes. peu importe.

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!")

Toutes les questions sont libres de poser.


J'ai essayé votre méthode et cela fonctionne bien mais je ne comprends pas comment ajouter un fichier à l'option file_resurces pour créer un fichier dans le fichier .exe. J'ai modifié le fichier build_exe.py comme vous l'avez dit, mais quand je vais dans le fichier setup.py et que j'écris, \'file_resources': [('txt2.txt')]cela me donne une erreur (le fichier que je veux embler dans mon .exe s'appelle txt2 et c'est un fichier .txt )
VinceLomba

Vous avez parlé de la façon dont vous avez converti toutes vos images en bitmats, puis tous vos fichiers de données en chaînes de texte. Même si vous avez dit que cela rend l'exe grand, cela fonctionne-t-il et si oui, pouvez-vous me dire comment faire cela? Je sais que cette réponse est assez ancienne, mais si vous pouvez répondre, cela sera apprécié.
Peppa

4

Vous devez créer un programme d'installation, comme mentionné précédemment. Même s'il est également possible de laisser py2exe regrouper tout dans un seul exécutable, en définissant l'option bundle_files sur 1 et l'argument du mot clé zipfile sur None, je ne le recommande pas pour les applications PyGTK.

C'est parce que GTK + tente de charger ses fichiers de données (locaux, thèmes, etc.) à partir du répertoire à partir duquel il a été chargé. Vous devez donc vous assurer que le répertoire de votre exécutable contient également les bibliothèques utilisées par GTK + et les répertoires lib, share et etc. de votre installation de GTK +. Sinon, vous rencontrerez des problèmes lors de l'exécution de votre application sur une machine sur laquelle GTK + n'est pas installé à l'échelle du système.

Pour plus de détails, lisez mon guide sur py2exe pour les applications PyGTK . Il explique également comment regrouper tout, sauf GTK +.


1

On m'a dit que bbfreeze créera un seul fichier .EXE, et qu'il est plus récent que py2exe.


3
Autant que je sache, bbfreeze ne produit pas d'exécutables à un seul fichier. Pouvez-vous documenter votre réponse?
joaquin

-2

J'ai récemment utilisé py2exe pour créer un exécutable pour la post-révision pour l'envoi de critiques à ReviewBoard.

C'était le setup.py que j'ai utilisé

from distutils.core import setup
import py2exe

setup(console=['post-review'])

Il a créé un répertoire contenant le fichier exe et les bibliothèques nécessaires. Je ne pense pas qu'il soit possible d'utiliser py2exe pour obtenir un seul fichier .exe. Si vous en avez besoin, vous devrez d'abord utiliser py2exe, puis utiliser une forme d'installation pour créer l'exécutable final.

Une chose à prendre en compte est que tous les fichiers egg que vous utilisez dans votre application doivent être décompressés, sinon py2exe ne peut pas les inclure. Ceci est couvert dans la documentation py2exe.


-2

essayez c_x freeze cela peut créer un bon standalone


cx_Freeze ne peut pas créer d'exécutable autonome, en fait, la documentation de cx_Freeze sur buildmedia.readthedocs.org/media/pdf/cx-freeze/latest/… dit, "cx_Freeze ne prend pas en charge la construction d'un fichier exe unique, où tous les les bibliothèques de votre application sont intégrées dans un fichier exécutable. " Pour plus de détails sur les exécutables autonomes dans cx_Freeze, allez dans la documentation ( buildmedia.readthedocs.org/media/pdf/cx-freeze/latest/… ) et allez à la section 4.5.
Peppa

-6

Non, cela ne vous donne pas un seul exécutable dans le sens où vous n'avez qu'un seul fichier par la suite - mais vous avez un répertoire qui contient tout ce dont vous avez besoin pour exécuter votre programme, y compris un fichier exe.

Je viens d'écrire ce setup.py aujourd'hui. Il vous suffit d'appeler python setup.py py2exe.


1
Ce n'est pas exact. Avec les bonnes options, vous pouvez obtenir un fichier autonome.
trevorKirkby

@Torsten Marek ... le lien vers votre setup.py est mort. En particulier .. les deux premiers redéfinitions finissent par promouvoir des trucs commerciaux. La troisième fois, cela se termine ici dans l'impasse d'Internet.
ZF007
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.