Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 22/06/2018, à 08:05

monsitt

Script Python (qui utilise PyInstaller) pour créer des exécutables

Bonjour à tous,

Voilà tout est dans le titre. Je viens de finir un script Python pour créer des exécutables à partir de projets codés en Python (Python 3 de préférence). J'ai découvert il y a peu PyInstaller, et j'avoue que je suis très séduit (et mon script utilise PyInstaller pour créer les exécutables). Pour l'instant le script ne compilera que des projets simples (je suis très loin de maîtriser toutes les possibilités offertes par PyInstaller).

Je n'ai testé mon script que pour un projet perso sous GNU/Linux, je n'ai pas eu le temps de le tester sous windows ... si quelqu'un ici pouvait le faire avec un de ses projets en Python, ce serait vraiment bien (pour cela il faudra renseigner la variable py_installer_windows dans le script).

Le fonctionnement du script est précisé dans le code (voir en dessous) :

#!/usr/bin/python
#-*- coding: utf-8 -*-

#-------------------------------------------------------------------------------
# Auteur :      Lama Angelo
# Copyright :   (c) Lama Angelo
#-------------------------------------------------------------------------------
# Licence : Ce script est placé GPL version 3, il régi par les quatre 
# libertés qui sont : la liberté d'utiliser le logiciel à n'importe quelle fin,
# la liberté de modifier le programme pour répondre à ses besoins, la liberté 
# de redistribuer des copies à ses amis et voisins, la liberté de partager 
# avec d'autres les modifications qu'il a faites.
#-------------------------------------------------------------------------------
# A quoi il sert ? :
# Ce script (qui n'a pas  encore de nom) se sert de PyInstaller pour 
# créer/compiler des exécutables (très facilement) à partir de scripts ou 
# applications écrit(es) en langage Python (de préférence en Python 3). Il 
# permet de créer des exécutables (aussi bien sous GNU/Linux, que sous Windows) 
# avec une arborescence standart (le script main *.py à la racine avec ou non 
# des répertoires, ... sous-répertoires contenant les modules annexes, mais 
# aussi des données sous forme [par exemple] d'images PNG, JPEG, ... mais aussi 
# de fichiers html, des fichiers texte, ...). 
# En somme ce script permet de rendre votre application portable.
#-------------------------------------------------------------------------------
# Prérequis : avoir installé PyInstaller ... voir ici : 
# https://www.pyinstaller.org/
#-------------------------------------------------------------------------------
# Précisions : le script permet aussi de travailler dans un environnement 
# virtuel Python (Virtualenv), c'est à dire dans une arborescence Virtualenv.
# La variable : ensemble_sous_rep_a_exclure est réglée pour pouvoir fonctionner
# avec à la fois l'arborescence d'un envoronnement virtuel Python et 
# l'arborescence de PyInstaller. Normalement cette variable n'est pas à modifier.
#-------------------------------------------------------------------------------
# Utilisation : Les variables générales du script (juste en dessous) doivent 
# être modifiées et adaptées aux spécificités de votre projet (codé en Python).
# Votre projet est compilé à sa racine (c'est à dire que vous verrez 
# certainement apparaître les répertoires build et dist).
# ---> Si vous laissez la variable ONE_FILE_DIR à la valeur "file", votre 
# exécutable sera compilé dans le répertoire : nom_de_votre_application_version 
# (par exemple dans un de mes projets personnels nommé APSC, ce sera dans le 
# répertoire : apsc_0_0_1). Dans ce cas (ONE_FILE_DIR = "file"), il n'y aura que 
# l'exécutable qui sera crée (celui-ci contiendra toutes les librairies utiles
# au bon fonctionnement de votre application). Eventuellement (si votre projet 
# contient des données dans son arborescence ; par exemple des fichiers html, 
# des images ou quoi que ce soit d'autre indispensable à son fonctionnement), 
# il faudra indiquer les extensions dans la liste liste_extensions. Dans ce cas
# vos répertoires/sous-répertoires et les données seront recrées dans le
# répertoire nom_de_votre_application_version. A la toute fin une archive zip
# sera crée.
# ---> Si vous décidez de donner le paramètre "dir" à la variable ONE_FILE_DIR,
# l'exécutable, toutes les librairies, ... éventuellement les données comme des 
# images, des fichiers html, ... seront crées/compilées dans un répertoire nommé 
# nom_de_votre_application_version, qui se retrouvera dans le répertoire dist.
# A la toute fin une archive zip sera crée.
# Pour lancer le script, il faut se placer (dans une console sous GNU/Linux, ou 
# dans une fenêtre MS/DOS sous sindows) dans le répertoire (à la racine) de 
# votre projet et taper la commande :
# python pyinstaller_creation_executable.py
#-------------------------------------------------------------------------------

import os, glob, subprocess, shutil


#############################################################
# --------------------------------------------------------- #
# Variables générales (PEUVENT ETRE MODIFEES)
# --------------------------------------------------------- #
# Nom court de l'application (en minuscules)
APPLI = "apsc"
# --------------------------------------------------------- #
# Version de l'application
VERSION_APPLI = "0.0.1"
# --------------------------------------------------------- #
# Nom du script principal (pour lancer  
# l'application) avec son extension
SCRIPT_MAIN = 'apsc_gui.py' 
# --------------------------------------------------------- #
# Si la variable est définie à file, la compilation se fait 
# avec le paramètre : --onefile, autrement si la variable est 
# définie à dir, la compilation se fait avec avec le paramètre 
# --onedir
# La différence entre les deux est que avec --onefile, un 
# exécutable seul est crée (et dans cet exécutable toutes 
# les librairies sont incluses) et avec --onedir, un 
# répertoire est crée (avec le nom de l'APPLI) ; dans ce 
# répertoire il y aura toutes les librairies, les 
# sous-répertoires et l'exécutable. 
ONE_FILE_DIR = "file" 
# --------------------------------------------------------- #
# Commande pour la complilation à exécuter
# --------------------------------------------------------- #
# Chemin de PyInstaller sous Windows + pyinstaller.exe
# UNIQUEMENT sous Windows !!! --> A adapter après install de
# PyInstaller sous Windows.
py_installer_windows = ""
# Chemin de PyInstaller sous GNU/Linux
py_installer_linux = 'pyinstaller'
# --------------------------------------------------------- #
# L'application possède-t-elle une interface graphique ?
# (oui ou non ?, la variable GUI est définie à oui par défaut)
# --------------------------------------------------------- #
GUI = 'oui'
# --------------------------------------------------------- #
# FICHIERS A INCLURE ... A DETECTER ...
# Extensions de fichier à détecter et présents dans l'arborescence du projet, par exemple :
# liste_extensions = ['.png', '.txt', '.html']
# S'il n'y a pas de fichiers à inclure, laisser la 
# liste vide ( --> liste_extensions = [] )
# --------------------------------------------------------- #
liste_extensions = ['.png']
# --------------------------------------------------------- #
# Sous-répertoires du chemin à exclure au moment de la compilation
# par PyInstaller (--> définis dans un ensemble set() )
# Cette variable n'a certainement pas besoin d'être changée
ensemble_sous_rep_a_exclure = {'__pycache__', 'lib', 'bin', 'build', 'dist', 'include', '{}_{}'.format(APPLI, VERSION_APPLI.replace('.', '_'))}
# --------------------------------------------------------- #
#############################################################


class Installeur() :
    # Classe Installeur
    def __init__(self):

        # Répertoire de travail
        self.rep_parent = os.getcwd()
        
        # Condition pour l'interface graphique
        if GUI == "oui" : self.windowed = "--windowed"
        else : self.windowed = ''

    def recherche_datas(self) :
        # --------------------------------------------------------- #
        # Recherche et mise en place des datas (par ex les images PNG)
        # --------------------------------------------------------- #
        liste_pre_data = []
        # Boucle qui génère l'arborescence du répertoire de travail
        for chem_parent, sous_reps, fichiers in os.walk(self.rep_parent, topdown=False):
            for nom in fichiers :
                # Reconstitution des chemins
                chemin = os.path.join(chem_parent, nom)
                # Détection de l'extension des fichiers
                detect_ext = os.path.splitext(chemin)[1]
                # Si le chemin est bien un fichier et qu'il 
                # comporte bien les extensions sélectionnées
                if os.path.isfile(chemin) and detect_ext in liste_extensions :
                    # La liste est remplie avec tous 
                    # les chemins en question
                    liste_pre_data.append(chemin)

        # Création d'un ensemble (--> set()) à la
        # racine ... c'est un set comprehension
        ensemble_fich_rep_parent = {ee1 for ee1 in liste_pre_data}
        # Création de l'ensemble
        select_chemins_a_exclure = set()
        # Boucle principale de recherche
        for ens1 in ensemble_fich_rep_parent :
            for ens2 in ensemble_sous_rep_a_exclure :
                # Si on trouve les sous-répertoires 
                # à exclure dans les chemins ...
                if ens2 in ens1 :
                    # ... on entre les valeurs détectées. Dans
                    # cet ensemble, les chemins comportant les
                    # sous-répertoires incluant les éléments
                    # présents dans l'ensemble :
                    # select_chemins_a_exclure sont sélectionnés
                    select_chemins_a_exclure.add(ens1)
                    
        # Pour finir ne sont sélectionnés que les chemins faisant partie de l'application,
        # c'est à dire, ceux comportant les données à compiler par PyInstaller
        set_diff_final = ensemble_fich_rep_parent.difference(select_chemins_a_exclure)
        # Conversion en liste
        data = list(set_diff_final)
        # On ne récupère que les chemins sans le nom du fichier
        #self.data_final = [os.path.dirname(base) for base in data]
        self.data_f = [base for base in data]
        print("self.data_f :", self.data_f)
        # On récupère le chemin du fichier avec son extension
        self.fich_ext = [os.path.splitext(f) for f in self.data_f]


    def onedir(self) :
        # ======================================================= #
        # Compilation avec --onedir (toutes les librairies
        # et l'exécutable sont crées dans le répertoire du nom de
        # l'application à la fin de la compilation)
        # ======================================================= #      
        
        # Appel de la fonction recherche_datas
        self.recherche_datas()

        # Liste de tuples qui récupère le chemin (avec un joker + .extension) + le nom 
        # du sous répertoire, sous la forme : 
        # [('/home/toto/projet_APSC_py3_pyqt5/smileys_evaluation/*.png', 'smileys_evaluation/.'), 
        # ('/home/toto/projet_APSC_py3_pyqt5/affichage_apsc/*.png', 'affichage_apsc/.'), ...]
        l_final_chem_ext = [[os.path.dirname(ch)+os.sep+"*"+ext, os.path.basename(os.path.dirname(ch))+os.sep+"."] for ch, ext in self.fich_ext if os.path.exists(ch+ext) and len(liste_extensions) > 0]

        # Pour éliminer les doublons dans la liste, j'ai utilisé cette méthode :
        # https://openclassrooms.com/forum/sujet/eliminer-doublons-d-une-liste-12668#message-7047669
        liste_finale_sans_doublons = [l_final_chem_ext[i] for i, _ in enumerate(l_final_chem_ext) if l_final_chem_ext[i] not in l_final_chem_ext[:i]]

        # Mise en forme finale (en chaînes de caractères)
        add_files_final = ""
        #for parc1, parc2 in l_final_chem_ext :
        for parc1, parc2 in liste_finale_sans_doublons :
            add_files_final += "\n\t( '{}', '{}' ),".format(parc1, parc2)

        # ------------------------------------- #
        # Variables d'écriture du fichier spec
        # (normalement à ne pas modifier)
        # ------------------------------------- #
        # Entêtes
        mode_python = "# -*- mode: python -*-"+"\n\n"
        block_cipher = "block_cipher = None"+"\n\n\n"
        # Fichiers (datas) de l'arborescence ajoutés pour le spec
        # [:-1] pour retirer la dernière virgule. 
        # Précisions ; si la liste liste_extensions est vide (c'est à dire
        # que l'utilisateur n'a pas rentré d'extension(s) de fichier(s) à
        # rechercher, added_files ne contiendra aucune donnée à inclure
        # pour la construction du fichier spec
        if len(liste_extensions) > 0 :
            add_files = "added_files = [{}\n\t]".format(add_files_final[:-1])
        else : add_files = "added_files = []"
        # Fonction Analysis
        a1 = "\na = Analysis(['{}'],".format(SCRIPT_MAIN)
        a2 = "\n\tpathex=['{}'],".format(self.rep_parent)
        a3 = "\n\tbinaries=[],"
        a4 = "\n\tdatas=added_files,"
        a5 = "\n\thiddenimports=[],"
        a6 = "\n\thookspath=[],"
        a7 = "\n\truntime_hooks=[],"
        a8 = "\n\texcludes=[],"
        a9 = "\n\twin_no_prefer_redirects=False,"
        a10 = "\n\twin_private_assemblies=False,"
        a11 = "\n\tcipher=block_cipher)"
        # PYZ
        a = a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11
        # Fonction PYZ
        pyz1 = "\npyz = PYZ(a.pure, a.zipped_data,"
        pyz2 = "\n\tcipher=block_cipher)"
        pyz = pyz1+pyz2
        # Fonction EXE
        exe1 = "\nexe = EXE(pyz,"
        exe2 = "\n\ta.scripts,"
        exe3 = "\n\texclude_binaries=True,"
        exe4 = "\n\tname='{}',".format(APPLI)
        exe5 = "\n\tdebug=False,"
        exe6 = "\n\tstrip=False,"
        exe7 = "\n\tupx=True,"
        exe8 = "\n\tconsole=False)"
        exe = exe1+exe2+exe3+exe4+exe5+exe6+exe7+exe8
        # Fonction COLLECT
        col1 = "\ncoll = COLLECT(exe,"
        col2 = "\n\ta.binaries,"
        col3 = "\n\ta.zipfiles,"
        col4 = "\n\ta.datas,"
        col5 = "\n\tstrip=False,"
        col6 = "\n\tupx=True,"
        col7 = "\n\tname='{}_{}')".format(APPLI, VERSION_APPLI.replace('.', '_'))
        col = col1+col2+col3+col4+col5+col6+col7
        
        # ------------------------------------- #
        # Chaîne de caractère du spec final
        # ------------------------------------- #    
        spec_final = mode_python+block_cipher+add_files+a+pyz+exe+col

        print("\nVOICI LE CONTENU DU FICHIER SPEC FINAL :\n----------------------------------------\n\n{}\n".format(spec_final))

        # ---------------------------------- #
        # Ecriture du fichier spec dans
        # le répertoire courant 
        # ---------------------------------- #
        fichier = open(SCRIPT_MAIN[:-3]+".spec", "w")
        fichier.write(spec_final)
        fichier.close()
        
        # Commande (PyInstaller), suivant le choix de l'utilisateur
        if os.name == 'nt' : commande = "{} --onedir {} {}.spec".format(py_installer_windows, self.windowed, SCRIPT_MAIN[:-3])
        else : commande = "{} --onedir {} {}.spec".format(py_installer_linux, self.windowed, SCRIPT_MAIN[:-3]) 
   
        # Méthode différente pour l'appel de subprocess, suivant les os (GNU/Linux ou windows)
        if os.name == 'nt' : subprocess.call(commande, stdin=file('nul','a'), stdout=file('nul','a'), stderr=file('nul','a'), shell = True)
        else : subprocess.call(commande, shell = True)
        
        # Création de l'archive zip en vue de la distribution ...
        shutil.make_archive(self.rep_parent+os.sep+'dist'+os.sep+APPLI+'_'+VERSION_APPLI.replace('.', '_'),'zip', self.rep_parent+os.sep+'dist'+os.sep+APPLI+'_'+VERSION_APPLI.replace('.', '_'))
        
        print("")
        print("# ------------------------------------- #")   
        print("Commande de PyInstaller : {}".format(commande))
        print("# ------------------------------------- #")
        print("Creation du fichier SPEC et compilation (dans le répertoire dist \n-->{}{}dist{}{})\nréussie !!!".format(self.rep_parent, os.sep, os.sep, APPLI))
        print("# ------------------------------------- #")
        print("Création de l'archive {}.zip (dans le\nrépertoire dist) réussie !!!".format(os.path.basename(self.rep_parent+os.sep+'dist'+os.sep+APPLI)))
        print("# ------------------------------------- #")
        print("")
        

    def onefile(self) :
        # ======================================================= #
        # Compilation avec --onefile (toutes les librairies
        # sont encapsulées dans l'exécutable --> un seul fichier)
        # ======================================================= #
    
        # Appel de la fonction recherche_datas
        self.recherche_datas()

        # Chemin du répertoire à créer
        chem_copie = self.rep_parent+os.sep+APPLI+'_'+VERSION_APPLI.replace('.', '_')

        try :
            if os.path.isdir(chem_copie) : 
                shutil.rmtree(chem_copie, onerror = remShut)
        except : pass

        # Commande (PyInstaller), suivant le choix de l'utilisateur
        if os.name == 'nt' : 
            commande = "{} --clean {} --onefile --distpath {}_{} --name {} {}".format(py_installer_windows, self.windowed, APPLI, VERSION_APPLI.replace('.', '_'), APPLI, SCRIPT_MAIN)
        else :
            commande = "{} --clean {} --onefile --distpath {}_{} --name {} {}".format(py_installer_linux, self.windowed, APPLI, VERSION_APPLI.replace('.', '_'), APPLI, SCRIPT_MAIN) 

        # Méthode différente pour l'appel de subprocess, suivant les os (GNU/Linux ou windows)
        if os.name == 'nt' : subprocess.call(commande, stdin=file('nul','a'), stdout=file('nul','a'), stderr=file('nul','a'), shell = True)
        else : subprocess.call(commande, shell = True)
  
        # ------------------------------------------------------- #
        # 
        # ------------------------------------------------------- #
        # si la liste liste_extensions contient au moins une donnée 
        # (c'est à dire que l'utilisateur a des fichiers [.png, 
        # .html, .txt, ... ] à inclure à l'archive ...
        if len(liste_extensions) > 0 :
            # Boucle principale
            for chem_parent in self.data_f : 
                # Sépare le sous-répertoire du reste du chemin
                # (cp --> chemin parent, sp --> sous-répertoire)
                cp, sp = os.path.split(os.path.dirname(chem_parent))
                # Crée les sous-répertoires dans le chemin (chem_copie)
                os.makedirs(chem_copie+os.sep+sp, exist_ok=True)
                # Listage des fichiers contenus dans le chemin
                for filename in os.listdir(os.path.dirname(chem_parent)) :
                    # Si le nom du sous répertoire est contenu dans le chemin et que
                    # les extensions de fichiers sont les bonnes ...
                    if sp in chem_parent and os.path.splitext(filename)[1] in liste_extensions :
                        # ... alors les fichiers sont bien copiés dans le 
                        # nouveau chemin défini, c'est à dire (et par ex 
                        # sous GNU/Linux) : chem_copie + les sous-répertoires
                        shutil.copy(os.path.dirname(chem_parent)+os.sep+filename, chem_copie+os.sep+sp)
        # ------------------------------------------------------- #

        # Création de l'archive zip en vue de la distribution ...
        shutil.make_archive(chem_copie,'zip', chem_copie)

        print("")
        print("# ------------------------------------- #")   
        print("Commande de PyInstaller : {}".format(commande))
        print("# ------------------------------------- #")
        print("Creation de l'exécutable. Compilation dans le répertoire\n--> {} réussie !!!".format(chem_copie))
        if len(liste_extensions) > 0 :
            print("# ------------------------------------- #")
            print("Distribution et copie des fichiers de {}".format(APPLI.upper()))
            print("en version {} réussie !!!".format(VERSION_APPLI))
        print("# ------------------------------------- #")
        print("Création de l'archive {}.zip réussie !!!".format(os.path.basename(chem_copie)))
        print("# ------------------------------------- #")
        print("")
    

if __name__ == '__main__':
    inst = Installeur()
    # Si la variable est définie à dir, c'est 
    # la fonction onedir qui est appelée,
    # autrement c'est la fonction onefile
    # qui est appelée
    if ONE_FILE_DIR == "dir" : inst.onedir()
    if ONE_FILE_DIR == "file" : inst.onefile()

Voici le résultat d'une compilation avec mon projet actuel (l'exécutable est réalisé avec la syntaxe --onefile de PyInstaller) :

(projet_APSC_py3_pyqt5) angelo@angelo-kubuntu:~/projet_APSC_py3_pyqt5$ python pyinstaller_creation_executable.py
self.data_f : ['/home/angelo/projet_APSC_py3_pyqt5/smileys_evaluation/smiley_pas_content_orange_18x18.png', '/home/angelo/projet_APSC_py3_pyqt5/affichage_apsc/apsc_oubli_de_charger_une_ref_art.png', '/home/angelo/projet_APSC_py3_pyqt5/smileys_evaluation/smiley_content_vert_18x18.png', '/home/angelo/projet_APSC_py3_pyqt5/smileys_evaluation/smiley_neutre_jaune_18x18.png']
514 INFO: PyInstaller: 3.3.1
514 INFO: Python: 3.4.3
514 INFO: Platform: Linux-3.19.0-71-generic-x86_64-with-Ubuntu-14.04-trusty
522 INFO: wrote /home/angelo/projet_APSC_py3_pyqt5/apsc.spec
523 INFO: UPX is not available.
524 INFO: Removing temporary files and cleaning cache in /home/angelo/.cache/pyinstaller
553 INFO: Extending PYTHONPATH with paths
['/home/angelo/projet_APSC_py3_pyqt5', '/home/angelo/projet_APSC_py3_pyqt5']
553 INFO: checking Analysis
553 INFO: Building Analysis because out00-Analysis.toc is non existent
553 INFO: Initializing module dependency graph...
574 INFO: Initializing module graph hooks...
575 INFO: Analyzing base_library.zip ...
2414 INFO: Processing pre-find module path hook   distutils
2414 INFO: distutils: retargeting to non-venv dir '/usr/lib/python3.4/distutils'
4134 INFO: running Analysis out00-Analysis.toc
4149 INFO: Caching module hooks...
4151 INFO: Analyzing /home/angelo/projet_APSC_py3_pyqt5/apsc_gui.py
5149 INFO: Loading module hooks...
5149 INFO: Loading module hook "hook-PyQt5.py"...
5161 INFO: Loading module hook "hook-pydoc.py"...
5168 INFO: Loading module hook "hook-PyQt5.QtCore.py"...
5462 INFO: Loading module hook "hook-PIL.py"...
5484 INFO: Excluding import 'PySide'
5484 INFO:   Removing import of PySide from module PIL.ImageQt
5484 INFO: Import to be excluded not found: 'tkinter'
5484 INFO: Excluding import 'PyQt4'
5485 INFO:   Removing import of PyQt4 from module PIL.ImageQt
5485 INFO: Excluding import 'PyQt5'
5486 INFO:   Removing import of PyQt5.QtGui from module PIL.ImageQt
5486 INFO:   Removing import of PyQt5.QtCore from module PIL.ImageQt
5486 INFO: Import to be excluded not found: 'FixTk'
5486 INFO: Loading module hook "hook-PIL.Image.py"...
6021 INFO: Loading module hook "hook-xml.py"...
6253 INFO: Loading module hook "hook-PyQt5.QtGui.py"...
6475 INFO: Loading module hook "hook-PyQt5.QtWidgets.py"...
6476 INFO: Loading module hook "hook-distutils.py"...
6478 INFO: Loading module hook "hook-sysconfig.py"...
6479 INFO: Loading module hook "hook-encodings.py"...
6516 INFO: Loading module hook "hook-PyQt5.Qt.py"...
6517 INFO: Loading module hook "hook-PIL.SpiderImagePlugin.py"...
6536 INFO: Excluding import 'tkinter'
6536 INFO: Import to be excluded not found: 'FixTk'
6536 INFO: Loading module hook "hook-PyQt5.QtPrintSupport.py"...
6569 INFO: Looking for ctypes DLLs
6757 INFO: Analyzing run-time hooks ...
6760 INFO: Including run-time hook 'pyi_rth_qt5.py'
6764 INFO: Looking for dynamic libraries
9246 INFO: Looking for eggs
9247 INFO: Python library not in binary dependencies. Doing additional searching...
9327 INFO: Using Python library /usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0
9330 INFO: Warnings written to /home/angelo/projet_APSC_py3_pyqt5/build/apsc/warnapsc.txt
9353 INFO: Graph cross-reference written to /home/angelo/projet_APSC_py3_pyqt5/build/apsc/xref-apsc.html
9386 INFO: checking PYZ
9386 INFO: Building PYZ because out00-PYZ.toc is non existent
9386 INFO: Building PYZ (ZlibArchive) /home/angelo/projet_APSC_py3_pyqt5/build/apsc/out00-PYZ.pyz
9693 INFO: Building PYZ (ZlibArchive) /home/angelo/projet_APSC_py3_pyqt5/build/apsc/out00-PYZ.pyz completed successfully.
9708 INFO: checking PKG
9708 INFO: Building PKG because out00-PKG.toc is non existent
9708 INFO: Building PKG (CArchive) out00-PKG.pkg
46442 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
46462 INFO: Bootloader /home/angelo/projet_APSC_py3_pyqt5/lib/python3.4/site-packages/PyInstaller/bootloader/Linux-64bit/run
46462 INFO: checking EXE
46462 INFO: Building EXE because out00-EXE.toc is non existent
46462 INFO: Building EXE from out00-EXE.toc
46505 INFO: Appending archive to ELF section in EXE apsc_0_0_1/apsc
47322 INFO: Building EXE from out00-EXE.toc completed successfully.

# ------------------------------------- #
Commande de PyInstaller : pyinstaller --clean --windowed --onefile --distpath apsc_0_0_1 --name apsc apsc_gui.py
# ------------------------------------- #
Creation de l'exécutable. Compilation dans le répertoire
--> /home/angelo/projet_APSC_py3_pyqt5/apsc_0_0_1 réussie !!!
# ------------------------------------- #
Distribution et copie des fichiers de APSC
en version 0.0.1 réussie !!!
# ------------------------------------- #
Création de l'archive apsc_0_0_1.zip réussie !!!
# ------------------------------------- #

Dans un certain futur je vais recoder le script avec une interface graphique.

Voilà, j'attends vos retours, ... si cela peut intéresser quelqu'un.

a+

Hors ligne