IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

QProcess dans une boucle [Python 3.X]


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 51
    Par défaut QProcess dans une boucle
    Bonjour,

    Je développe une petite application sous Linux (mais peu importe puisqu'en python) qui a besoin de lancer des commandes ffmpeg depuis une liste d'url. Pour chaque commande ffmpeg, je veux pouvoir afficher la progression de cette commande. Mon problème est que ces commandes mettent beaucoup de temps à être effectuée, ce qui déclenche un timeout du QProcess sauf si j'utilise WaitForFinished(-1). Cependant, utliliser WaitForFinished(-1) comme je le fais provoque l'affichage du message "main.py ne répond pas, attendre ou forcer à quitter".

    J'ai du mal à imaginer une autre solution car je débute en python et que ça touche des concepts que je ne maîtrise pas encore.

    Je vous mets donc quelques portions intéressantes du code pour que vous puissiez m'aider si possible.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            # Lancement des téléchargements
            for i in range(self.listDL.count()):
                epItem: CustomListWidgetItem = self.listDL.item(i)
                epData = self.client.makeRequest("Épisode", epItem.id)
                ...
                        # Récupération de la liste de lecture finale
                        if self.getFinalM3u8(url, epData['id']):
                            # Téléchargement avec FFMPEG
                            m3u8 = f"{os.getcwd()}/downloads/{epData['id']}.m3u8"
                            cmdLine = f"-protocol_whitelist file,http,https,tcp,tls,crypto,data -y -i \"{m3u8}\" -c copy -bsf:a aac_adtstoasc \"{os.getcwd()}/downloads/{fileName}.mp4\" -v quiet -stats"
                            self.file = f"{os.getcwd()}/downloads/{fileName}.mp4"
                            self.startDownload(cmdLine)
                            self.p.waitForFinished(-1)
                            os.remove(m3u8)
    En gros, le code ci-dessus récupère, pour chaque élément de self.listDL, un fichier m3u8 qui va ensuite être ouvert avec FFMPEG pour télécharger la vidéo associée. Comme vous le voyez, un QProcess (self.p) est initialisé dans la fonction self.startDownload() ci-dessous et j'ai effectué des connexions avec les événements du QProcess pour avoir la progression.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
        def startDownload(self, cmd: str):
            if self.p is None:
                self.message("Début du téléchargement...")
                self.p = QProcess()
                args = shlex.split(cmd)
                self.pbDL.setRange(0, 100)
                self.pbDL.setValue(0)
                self.p.readyReadStandardError.connect(self.handleProgress)
                self.p.finished.connect(self.dlFinished)
                self.p.start("ffmpeg", args)
     
        def handleProgress(self):
            data = self.p.readAllStandardError()
            stderr = bytes(data).decode("utf8")
            with open("error.txt", "+a") as out:
                out.write(stderr)
            if self.file != None:
                self.pbDL.setValue(round((os.stat(self.file).st_size / self.dlSize) * 100))
     
        def dlFinished(self):
            self.message("Téléchargement terminé.")
            self.p = None
            self.dlSize = None
            self.file = None
    Je précise que le code fonctionne, les téléchargements se font, tout est ok à part ce message. J'ai cru comprendre qu'il était possible de passer par un QThread mais je ne sais pas faire donc si quelqu'un veut bien m'indiquer (et m'expliquer) une solution, ce serait sympa. Il reste quelques détails à régler (comme par exemple l'utilisation d'os.path pouur gérer les chemins de façons à rendre l'outil multiplateforme) mais je suis ravi d'avoir réussi à faire ça déjà, ce serait dommage de bloquer sur un dernier détail.

    Merci d'avance.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 743
    Par défaut
    Citation Envoyé par Khyinn Voir le message
    Cependant, utliliser WaitForFinished(-1) comme je le fais provoque l'affichage du message "main.py ne répond pas, attendre ou forcer à quitter".
    WaitForFinished avec -1 bloque en attendant la fin du QProcess: ce que vous constatez est normal.

    Comme vous avez exécuté self.p.finished.connect(self.dlFinished), utiliser cette fonction de rappel a la place suffit (en y déplaçant l'os.remove(...) qui vient après).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 51
    Par défaut
    Ah oui, je crois comprendre. On supprime la boucle et à la place, dans la fonction lançant le QProcess, on traite uniquement le premier élément de la liste. Et dans le DLFinished, on fait un pop sur la liste, on vérifie qu'il reste un élément dans la liste et on relance startDownload si c'est le cas. C'est bien ça ?

  4. #4
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Que fait exactement ffmpeg comme transformation de cette vidéo ?

    S’il ne sert qu'à télécharger une vidéo en partant d'une liste de lecture m3u8 alors tu peux le faire avec urllib.request, c'est ce que je fais avec mon appli Qarte.

    Regarde ce code, il utilise un pyqtSignal pour afficher la progression de téléchargement; Pourcentage, vitesse, temps restant.

    https://bazaar.launchpad.net/~vincen...loader.py#L397

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 51
    Par défaut
    Merci VinsS pour cette réponse, c'est intéressant. C'est vrai que j'utilise FFMPEG un peu par facilité car je sais plutôt bien l'utiliser et surtout car j'encode ensuite la vidéo pour en réduire le poids en l'utilisant mais la solution d'utiliser resquest est tout à fait viable.

    Cela dit, j'ai procédé comme indiqué ce matin en supprimant la boucle et en réappellant la fonction startDownload() à la fin du QProcess si la liste n'est pas vide et cela fonctionne très bien Le souci est donc résolu ! Merci pour l'aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [langage] incrementation de variable dans une boucle
    Par mimilou dans le forum Langage
    Réponses: 15
    Dernier message: 16/04/2004, 13h23
  2. Problème avec TNMSMTP dans une boucle.
    Par Orgied dans le forum Web & réseau
    Réponses: 3
    Dernier message: 07/04/2004, 10h19
  3. swf dans une boucle asp
    Par Chucky69 dans le forum Flash
    Réponses: 11
    Dernier message: 10/02/2004, 17h07
  4. [Vb.net] Indexé un objet crée dans une boucle
    Par picpic dans le forum Windows Forms
    Réponses: 10
    Dernier message: 17/12/2003, 14h37
  5. Pause dans une boucle
    Par HT dans le forum Langage
    Réponses: 4
    Dernier message: 03/06/2003, 08h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo