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

PyQt Python Discussion :

Utilisation Qprocess et QThread pour la copie de fichiers (1To) [QtCore]


Sujet :

PyQt Python

  1. #1
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut Utilisation Qprocess et QThread pour la copie de fichiers (1To)
    Bonjour à tous,

    Je dois mettre en place une application ayant plusieurs buts :
    1) Copier tous les fichiers d'un support A vers un support B (avec dossier et sous-dossiers). En règle général cela concerne 1 à 2 To et quelques millions de fichiers.
    2) Traiter ces fichiers une fois la copie faite.


    Au départ j'ai voulu utiliser shutil.copytree pour faire le job, mais cela est carrément plus lent que de le faire avec le copier/coller de windows (30% en plus).
    J'ai essayer de trouver d'autres lib comme speedcopy ou pyfastcopy. Les deux ne donnent de véritable amélioration de résultat.

    Bref, comme l'app doit $etre faite avec PyQt, je me posais la question :
    Puis-je utiliser QProcess ou QThread pour faire le job et surtout pour avoir une amélioration des temps par rapport à shutil ?


    Ensuite, j'avoue que je m’emmêle souvent les pinceaux entre le multithreading et le multiprocessing

    Quels conseils vous auriez à me donner pour faire le job ?

    Je vous remercie de votre aide.
    Douter de tout, toujours, et surtout de soi-même...

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Vaste question et réel problème...

    Pour accélérer la copie, et si c'est sous Windows, peut-être faut-il essayer xcopy ou robocopy qui font partie de Windows et qui ont l'air assez rapides. Ils ont beaucoup de paramétres de configuration.

    Compte tenu du nombre de fichiers à copier, si cette opération devait être renouvelée périodiquement pour les 2 mêmes répertoires (source et destination), il faudrait voir du côté de la sauvegarde incrémentale. La fonction robocopy fait ça très bien (voir aussi pour info mon tuto pour une solution en pur Python: https://www.developpez.net/forums/d2...entale-python/)

    Si le copier-coller a l'air rapide, rien ne s'oppose à le déclencher sous Python.

    On peut effectivement utiliser QThread ou QProcess, mais je ne suis pas sûr qu'on y gagne beaucoup, dans la mesure où le matériel pour l'écriture physique sera probablement le goulot d'étranglement. Cependant, ça vaut peut-être le coup d'essayer?

    Entre les threads et les processus:

    - les threads sont des "processus léger" qui s’exécutent en fait dans le même processus que le programme principal. Et compte tenu du fonctionnement de Python (GIL), les traitements sont bien asynchrones (=ne s'attendent pas les uns les autres), mais sont exécutés les uns à la suite des autres dans le CPU sans avantage de temps. Avec cependant l'avantage d'un partage plus facile des données.

    - les processus sont différents, et peuvent s'exécuter dans des "cœurs" différents des CPU multicore modernes. Là, on gagne vraiment du temps. En contrepartie, les partages d'informations ne sont plus aussi faciles.

    Et entre QThread-QProcess de PyQt5 et les modules Python d'origine threading-multiprocessing, il vaut mieux utiliser les 1ers quand on travaille avec PyQt5 grâce à la facilité avec laquelle on peut alors échanger des messages avec le programme principal (par l'intermédiaire de signaux). Rappelons que ces exécutions asynchrones ne doivent pas toucher directement au graphique du programme principal.

    Dernier point. Quand on utilise les threads ou les processus, on peut avoir des opérations déclenchées simultanément qui rentrent en conflit. Si c'est le cas, il faudra utiliser des verrous.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Plein de questions dans tous les sens. Je vais essayer de clarifier un peu tout ça.
    Tout d'abord, la rapidité de la copie Windows (ce qui sous-entend que tu es sous Windows donc) par rapport à shutil.copytree est due au fait que la copie Windows inclut naturellement du multithread, ce que ne fait pas le coytree Python. Tu encapsulerais ce copytree dans du thread, je suis certain que tu obtiendrais le même résultat (après-tout, tout en bas du bas de la machine, la copie reste la copie). Toutefois tu te heurteras très vite au mur de la vitesse d'écriture disque qui restera infranchissable.

    Ensuite la différence entre multithread et multiprocess est avant tout historique. Quand Unix a été conçu (1963, un projet qui dure 5 ans, finalement abandonné tellement mal pensé et alors repensé de zéro et terminé en 2 ans) il a été conçu dès le départ multiprocesseur. C'était un OS fait pour ordinateurs industriels. Puis Windows est arrivé pour PC (un seul processeur à l'époque) puis quand les PC multiprocesseurs ont commencé à arriver, est alors sorti NT (New Technology) qui incluait le multithread. Pour simplifier grosso-modo, dans un programme multiprocessus, chaque processus est totalement indépendant de ses voisins. Il possède sa mémoire personnelle, et pourrait à la limite être le seul à faire tout le job. Tandis que dans un programme multithread, chaque thread ne possède qu'un segment de code, segment qui tout seul ne pourra pas faire le job s'il n'est pas associé aux autres segments traités par d'autres threads. Si on devait prendre un exemple de la vie réelle, un multiprocessus ce serait une cuisine de restaurant avec 12 cuisiniers qui cuisinent 12 plats différents pour 12 clients (un seul cuisinier pourrait faire tout le job) tandis qu'un multithread c'est dans ta cuisine, si tu veux faire des carottes aux oignons, tu prendras d'un côté une poele pour rissoler les oignons et d'un autre une casserole pour faire cuire les carottes, le tout sur la même cuisinière (mais ni les carottes ni les oignons, pris séparéments, ne font un plat de carottes aux oignons)

    Qt permet les deux mais le QProcess sera plutôt indiqué pour exécuter un code externe (un programme indépendant) tandis que QThread sera plus indiqué pour faire tourner deux objets Qt en même temps dans l'IHM (par exemple une QProgressBar qui indique l'état d'avancement se fera dans un QThread).

    Pour ta copie, ne sachant pas quelle solution sera la meilleure parmis toutes les possibles, je m'appuierais alors sur la philosophie Python (Simple is Better Than Complex) associée au principe MVC (séparer le Contrôle (le travail) de la Vue (ce qui s'affiche)) pour choisir. Ainsi je créerais un programme Python indépendant permettant de copier n fichiers, et j'incluerais ce programme dans des QProcess Qt (exemple https://qt.developpez.com/doc/4.7/qprocess/).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    @Sve@r, @tyrtamos,

    Je vous remercie, vos explications sont limpides . JE vais me pencher dessus, et je reviendrais peut-être poser une question subsidiaire.

    Bonne journée à vous
    Douter de tout, toujours, et surtout de soi-même...

  5. #5
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    Bonjour,

    Je reviens vers vous pour avoir vos avis sur quelques tests que j'ai effectués.

    Je suis parti sur un échantillon de fichiers et répertoires, dans un répertoires sources :

    Nombre de fichiers : 106 944
    Nombre de répertoires : 47
    Taille globale : 230,640 Mo

    J'ai ensuite fait des comparaisons de temps de copie avec xcopy, robocopy et Copy-Item à partir :
    1) powershell seul
    2) QProcess appelant powershell
    3) Subprocess appelant powershell.


    Je vous mets ci-dessous mes résultats :

    Xcopy

    A partir de PowerShell
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Measure-Command {xcopy C:\Users\xxx\Documents\Src C:\Users\xxx\Documents\Dst /s}
    Durée totale de la copie : 80,0700134 secondes

    A partir QProcess :
    Durée totale de la copie : 86,0846811 secondes

    A partir de Subprocess :
    Durée totale de la copie : 72,696 secondes


    Robocopy

    A partir de PowerShell
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Measure-Command {robocopy C:\Users\xxx\Documents\Src C:\Users\xxx\Documents\Dst /s}
    Durée totale de la copie : 95,0771276 secondes

    A partir de Qprocess :
    Durée totale de la copie : 81,6548262 secondes

    A partir de Subprocess :
    Durée totale de la copie : 80,992 secondes

    Copy-Item

    A partir de PowerShell
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Measure-Command {Copy-Item -Path 'C:/Users/xxx/Documents/Src/*' -Destination 'C:/Users/xxx/Documents/Dst/' -Recurse}
    Durée totale de la copie : 51,41224883 secondes

    A partir de QProcess :
    Durée totale : 82.2926631 secondes

    A partir de Subprocess :
    Durée totale de la copie : 60,032secondes


    Je vous mets ci-dessous mes scripts python

    QProcess :
    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
     
    import time
     
    from PyQt5.QtCore import QProcess
    src = "C:/Users/xxx/Documents/Src/*"
    dst = "C:/Users/xxx/Documents/Dst"
     
     
    t = time.time()
    proc = QProcess()
     
    def rendu():
        data = proc.readAllStandardOutput()
        stdout = bytes(data).decode("utf8")
        print(stdout)
     
    script = "Copy-Item -Path '" + src +"' -Destination '" + dst + "' -Recurse"
    script_xcopy = "xcopy '" + src +" " + dst + " /s"
    script_robo = "robocopy '" + src +" " + dst + " /e /z"
     
    proc.readyReadStandardOutput.connect(rendu)
    proc.start('powershell.exe', [script_robo])
    proc.waitForFinished(-1)

    et pour le Subprocess :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    import time
    import subprocess
     
    t= round(time.time()*1000)
     
    # cmd_robo = subprocess.run(["powershell.exe", "robocopy C:\\Users\\xxx\\Documents\\Src C:\\Users\\xxx\\Documents\\Dst  /e /z"], shell=True)
    # cmd_xcopy = subprocess.run(["powershell.exe", "xcopy C:\\Users\\xxx\\Documents\\Src C:\\Users\\xxx\\Documents\\Dst /s"], shell=True)
    cmd_copyItem  = subprocess.run(["powershell.exe", "Copy-Item -Path 'C:\\Users\\xxx\\Documents\\Src \\*' -Destination 'C:\\Users\\xxx\\Documents\\Dst' -Recurse"], shell=True)
    d= round(time.time()*1000)
     
    print (d-t)

    Auriez vous une explication ou des idées d'explications de ces résultats et en particulier sur les différences, assez énormes. J'ai fait ces tests sur 100 000 fichiers, je n'ose pas imaginé ce que cela devrait donner sur un échantillon de plus de 10 millions.

    Je précise que j'ai fait ces tests sur mon poste uniquement, d'un répertoire à un autre. Ce pc est sous W10 avec 16 Go de Ram et un SSD.

    Je vous remercie de votre analyse.
    Douter de tout, toujours, et surtout de soi-même...

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par FadeToBlack Voir le message
    Je précise que j'ai fait ces tests sur mon poste uniquement, d'un répertoire à un autre. Ce pc est sous W10 avec 16 Go de Ram et un SSD.
    Si vous avez mesuré qu'une seule fois, vos résultats peuvent dépendre de la sollicitation du disque dur par les autres activités du système. Çà demande à être répété un certain nombre de fois pour être "solide".

    Si c'est le cas, il faut regarder comment fonctionnent Xcopy, copy-item et robocopy...

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

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Je suis très étonné des piètres résultats de robocopy, parce qu'il est couramment tenu pour meilleur que xcopy. Peut-être faut-il voir du côté de ses options. En effet, robocopy est très complet, surtout pour la sécurité, mais fait aussi des choses qui ne sont pas forcément nécessaires ici. Un simple "robocopy /?" dans une console montre l'impressionnante liste des options.

    Par ailleurs, pour les essais successifs, attention aux caches utilisés pour les copies disques: il est fréquent que les copies suivantes soient meilleures parce que certains contenus sont prélevés dans les caches, ce qui est plus rapide que la lecture effective. Je l'ai déjà constaté pour les disques durs "normaux", mais je ne sais pas si ça joue pour un SSD.

    Je suis également étonné que QProcess soit moins bon que subprocess, et je n'en vois pas la raison. Je vais regarder ça de plus près.

    Si Copy-Item (spécifique powershell) est le meilleur, peut-être ne faut-il pas chercher plus loin. A mon avis, 50 secondes pour 106.000 fichiers, ce n'est pas mal du tout...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  8. #8
    Membre actif Avatar de FadeToBlack
    Homme Profil pro
    ...
    Inscrit en
    Août 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : ...
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Août 2010
    Messages : 311
    Points : 202
    Points
    202
    Par défaut
    Bonjour,

    Avec plusieurs jours de retard, je vous remercie de votre aide.

    Cela fonctionne correctement,

    Bonne journée
    Douter de tout, toujours, et surtout de soi-même...

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

Discussions similaires

  1. [XL-2007] utiliser l'outil consolider pour une soustraction de fichier?
    Par scoulibri dans le forum Excel
    Réponses: 4
    Dernier message: 20/03/2015, 12h00
  2. [PySide] QProcess ou QThread pour ce cas ?
    Par Einenlum dans le forum PyQt
    Réponses: 10
    Dernier message: 30/05/2014, 15h20
  3. Utilisation des Macro pour une copie et mise en forme
    Par Stephane59 dans le forum VBA Word
    Réponses: 6
    Dernier message: 09/02/2013, 15h07
  4. action play/pause pour une copie de fichiers via socket
    Par dumoulex dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 13/05/2011, 14h05
  5. Réponses: 3
    Dernier message: 02/05/2007, 08h20

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