Obtenir de l'avancement des travaux de shutil de copie de fichier thread
J'ai une application à partir de laquelle un fichier est copié à partir de src
à dst
:
import shutil
from threading import Thread
t = Thread(target=shutil.copy, args=[ src, dst ]).start()
Je souhaite avoir l'application de requête de la progression de la copie toutes les 5 secondes sans bloquer l'application elle-même. Est-ce possible?
Mon intention est de définir ce progrès pour un QtGui.QLabel
pour donner à l'utilisateur un retour sur la copie de fichier.
Cela peut-il être réalisé lors de la copie à l'aide d'une tige filetée shutil de copie de fichier?
- Hé, je crois que j'ai trouvé votre solution finale: fredrikaverpil.github.io/2015/05/12/.... Bonnes choses!
Vous devez vous connecter pour publier un commentaire.
shutil.copy()
n'offre pas toutes les options pour suivre les progrès, pas de. Tout au plus on pourrait contrôler la taille du fichier de destination (à l'aide deos.*
fonctions sur le nom de fichier cible).L'alternative consisterait à mettre en place votre propre fonction de copie. L'application est vraiment très simple;
shutil.copier()
est fondamentalement unshutil.copyfile()
plusshutil.copymode()
appel;shutil.copyfile()
à son tour, délègue le travail réel àshutil.copyfileobj()
(des liens vers le code source Python).La mise en œuvre de votre propre
shutil.copyfileobj()
d'inclure des progrès devraient être trivial; injecter de soutien pour une fonction de rappel pour le rapport d'informer votre programme chaque fois qu'un autre bloc a copié:et de comparer les
copied
taille avec la taille du fichier.J'ai combiné Martijn Pieters répondre des progrès de code à barres de cette réponse avec des modifications de travailler dans PyCharm de cette réponse qui me donne ce qui suit. La fonction
copy_with_progress
était mon objectif.Non, il ne peut pas être fait de cette façon, parce que
shutil.copy
n'ont pas les moyens de fournir progrès.Mais vous pouvez écrire votre propre fonction de copie (ou même un fork du code de
shutil
--avis que c'est l'un des modules qui comprend un lien vers la source au sommet, ce qui signifie qu'il est destiné à être aussi utile pour l'exemple de code pour pour l'utiliser en tant que-est). Votre fonction peut, par exemple, prendre un progrès fonction de rappel comme un argument supplémentaire et l'appelle après chaque tampon (ou chaque N tampons, ou chaque N octets, ou toutes les N secondes). Quelque chose comme:Maintenant, que le rappel est toujours en cours d'être appelé dans le thread d'arrière-plan, pas le thread principal. Avec la plupart des GUI cadres, ce qui signifie qu'il ne peut pas toucher directement l'interface graphique widgets. Mais la plupart des GUI cadres ont une façon de poster un message sur le thread principal de la boucle d'événements à partir d'un thread d'arrière-plan, il suffit donc de faire le rappel de le faire. Avec Qt-vous faire cela avec les signaux et les slots, exactement de la même façon que dans le thread principal; il y a beaucoup de tutoriels là-bas si vous ne savez pas comment.
Sinon, vous pouvez le faire de la manière que vous avez suggéré: avoir le thread principal signal le thread d'arrière-plan (par exemple, en postant sur un
queue.Queue
ou le déclenchement d'uneEvent
ouCondition
) et avoir votrecopy
fonction de vérifier que le signal de tous les temps à travers la boucle et d'y répondre. Mais qui semble à la fois plus complexe et moins réactif.Une chose de plus: Qt a son propre filetage de la bibliothèque, et vous pouvez l'utiliser au lieu de Python natif de l'un, parce que vous pouvez joindre une fente directement à
QThread
objet et assurez-vous que votre rappel. Je ne suis pas sûr, mais Qt pourrait même avoir sa propre copie de fichier-avec-les progrès des méthodes de quelque part; ils essaient de s'envelopper tout qui pourrait être à tous les différents entre les plates-formes et vaguement liés aux Interfaces graphiques.En plus de Martijn Pieters excellente réponse, si (comme moi, Je suis un idiot) vous avez besoin de savoir comment passer la réelle rappel dans le
copyfileobj()
fonction, vous pouvez le faire comme ceci:Cela peut être très orthodoxe, mais il fonctionne: