148 votes

py2exe - générer un seul fichier exécutable

Je pensais avoir entendu que py2exe a pu le faire, mais je n'ai jamais compris. Quelqu'un a-t-il réussi à le faire ? Puis-je voir votre fichier setup.py, et quelles options de ligne de commande vous avez utilisées ?

En gros, je pense qu'il doit me donner un seul fichier exécutable qui fait quelque chose comme se décompresser dans /temp et s'exécuter.

1 votes

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

175voto

minty Points 7864

La façon de le faire avec py2exe est d'utiliser l'option bundle_files dans votre fichier setup.py. Pour un seul fichier, vous voudrez définir bundle_files à 1, compressed à True, et définissez l'option zipfile à None. De cette façon, il crée un seul fichier compressé pour une distribution facile.

Voici une description plus complète de l'option bundle_file citée directement de la page d'accueil du site Web de la Commission européenne. site py2exe *

Utilisation de "bundle_files" et de "zipfile".

Une façon plus simple (et meilleure) de créer des des exécutables à un seul fichier est de définir bundle_files à 1 ou 2, et de donner à zipfile à None. Cette approche ne pas besoin d'extraire les fichiers dans un temporaire, ce qui permet un démarrage démarrage du programme beaucoup plus rapide.

Les valeurs valides pour bundle_files sont :

  • 3 (par défaut) ne pas regrouper les données
  • 2 regrouper tout sauf l'interpréteur Python
  • 1 regrouper tout, y compris l'interpréteur Python

Si zipfile est défini comme 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,
)

0 votes

Est-il possible de créer un fichier unique, qui dépend de la dll python ? Cela ne me dérange pas d'avoir 1 exe+1 dll (puisque la dll peut être installée à un endroit commun), tant que tous les petits fichiers de dépendance sont cachés dans l'exe.

6 votes

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

13 votes

Veuillez noter que bundle_files 1 n'est pas supporté sur amd64 (py2exe 0.6.9 pour Python 2.6 au moins).

108voto

dF. Points 29787

PyInstaller créera un seul fichier .exe sans aucune dépendance ; utilisez l'option --onefile option. Il le fait en empaquetant toutes les librairies partagées nécessaires dans l'exécutable, et en les dépaquetant avant qu'il ne s'exécute, comme vous le décrivez (EDIT : py2exe a aussi cette fonctionnalité, voir La réponse de Minty )

J'utilise la version de PyInstaller de svn, puisque la dernière version (1.3) est un peu dépassée. Il fonctionne très bien pour une application qui dépend de PyQt, PyQwt, numpy, scipy et quelques autres.

6 votes

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

0 votes

Veuillez noter qu'à partir de la version 1.4, PyInstaller ne supporte pas Python 2.6+ sous Windows.

2 votes

J'utilise maintenant la version 1.5.1, et elle fonctionne avec Python 2.7.2.

15voto

Bluebird75 Points 4612

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

L'étape suivante consiste à utiliser un installateur, pour regrouper tout cela dans un programme facile à installer et à désinstaller.

J'ai utilisé InnoSetup avec plaisir depuis plusieurs années et pour des programmes commerciaux, je le recommande donc chaleureusement.

1 votes

+1 pour avoir indiqué qu'après py2exe il y a encore des choses à empaqueter.

7voto

Nor Points 49

J'ai pu créer un seul fichier exe avec toutes les ressources intégrées dans l'exe. Je construis sous Windows, ce qui explique certains des appels système os.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 fait en sorte que l'exe final soit très très grand.

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

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

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

ceci explique tous les changements effectués, j'ai simplement ajouté une nouvelle option à la ligne setup. Voici mon setup.py.

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

ça vient d'un écran de veille que j'essayais de faire.

J'utilise exec pour générer ma configuration au moment de l'exécution, c'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])

ventilation

script = py script je veux transformer en un exe.

icon_resources = l'icône de l'exe

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

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

options = options de py2exe 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 n'avez pas modifié votre fichier py2exe.py comme décrit dans le lien ci-dessus.

C'est la première fois que j'essaye de poster un code sur ce site, si je me trompe, ne m'en voulez 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 nécessaire pour accéder aux images. J'ai développé cette application sans py2exe à l'esprit puis je l'ai ajouté plus tard. donc vous verrez l'accès pour les deux situations. si le dossier d'image ne peut pas être trouvé il essaie de tirer les images des ressources de l'exe. le code l'expliquera. ceci fait partie de ma classe de sprite et utilise un directx. mais vous pouvez utiliser n'importe quelle api que vous voulez ou juste accéder aux données brutes. cela n'a pas d'importance.

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

N'hésitez pas à poser vos questions.

0 votes

J'ai essayé votre méthode et elle fonctionne bien mais je ne comprends pas comment ajouter un fichier à l'option file_resurces pour incorporer un fichier dans le .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')] il me donne une erreur (le fichier que je veux incorporer dans mon .exe est nommé txt2 et c'est un fichier .txt)

0 votes

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 augmente la taille de l'exe, est-ce que cela fonctionne et si oui, pouvez-vous me dire comment faire ? Je sais que cette réponse est assez ancienne mais si vous pouvez y répondre, ce sera apprécié.

4voto

Sebastian Noack Points 458

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

C'est parce que GTK+ essaie de charger ses fichiers de données (locaux, thèmes, etc.) à partir du répertoire où 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, etc. de votre installation de GTK+. Sinon, vous aurez des problèmes pour exécuter votre application sur une machine où GTK+ n'est pas installé dans tout le système.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X