2016-09-21 2 views
0

Je transfère chaque jour un fichier de 150-200mb vers plusieurs emplacements (lecteurs partagés situés à travers le monde). Le problème est que chaque transfert (en utilisant shutil) prend probablement 100-700 secondes et que chacun doit se terminer pour que le prochain commence. Il faut maintenant une heure pour transférer certains fichiers si je le fais de cette façon. Ma solution temporaire consistait à créer un fichier .py distinct à exécuter pour chaque emplacement afin qu'ils puissent être exécutés simultanément, mais ce n'est pas idéal.Copie simultanée d'un fichier sur plusieurs chemins

Comment puis-je plonger dans la programmation multi-thread? Je voudrais exécuter tous les transferts à la fois mais je n'ai aucune expérience avec cela.

Une simple recherche Google m'a atterri avec:

https://docs.python.org/3/library/concurrent.futures.html.

import shutil 
with ThreadPoolExecutor(max_workers=4) as e: 
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt') 
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt') 
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt') 
    e.submit(shutil.copy, 'src4.txt', 'dest4.txt') 

Est-ce que quelqu'un peut me diriger dans la bonne direction? J'ai eu l'intention d'apprendre à faire les choses en parallèle pendant un moment maintenant mais je n'ai jamais réussi à le faire.

+0

Peut-être [ce poste] (http://stackoverflow.com/questions/20887555/dead-simple-example-of-using-multiprocessing-queue-pool-and-locking) vous aidera. J'ai trouvé la réponse acceptée comme un exemple utile. – PyNoob

+0

On dirait que vous pourriez aussi renommer les fichiers, c'est correct? – martineau

+0

Cet extrait de code provient des docs que j'ai liés (lorsque j'ai utilisé ctrl + F pour shutil). Je ne vais pas changer le nom si. shutil.copy2 ('../ dashboard.twbx', '// sharedpath/region/dashboard /') – trench

Répondre

1

Voici un exemple de travail qui fait ce que vous voulez. Notez qu'il ne peut pas être plus rapide qu'un seul à la fois si le goulot d'étranglement est la bande passante du réseau.

from concurrent.futures import ThreadPoolExecutor 
import os 
import shutil 
import time 
from threading import Lock 

src_dir = './test_src' 
src_files = 'src1.txt', 'src2.txt', 'src3.txt', 'src4.txt' 
dst_dir = './test_dst' 
print_lock = Lock() 

_print = print # save original 
def print(*args, **kwargs): 
    """Prevents concurrent printing.""" 
    with print_lock: 
     _print(*args, **kwargs) 

def copy_file(src_file): 
    src_file = os.path.join(src_dir, src_file) 
    print('starting transfer of "{}"'.format(src_file)) 
    shutil.copy2(src_file, dst_dir) 
    print('transfer of "{}" completed'.format(src_file)) 

with ThreadPoolExecutor(max_workers=4) as e: 
    jobs = [e.submit(copy_file, src_file) for src_file in src_files] 

while any(job.running() for job in jobs): 
    time.sleep(.1) 
print('done') 
+0

Salut, merci. J'ai essayé cela et il a copié le premier fichier mais pas le second. Il semblait que le code était encore en cours d'exécution et l'impression montrait "Commencer le transfert du nom de fichier" pour les deux, mais un seul était terminé et ensuite il était imprimé "terminé". Aussi, est-il possible de modifier cela pour se concentrer sur le partage d'un fichier vers plusieurs destinations? – trench

+0

Hmm, a travaillé pour moi localement (pas de/vers des emplacements sur mon réseau local, mais cela ne devrait pas importer). Si elle a imprimé 'done', alors tous les appels' shutil.copy2() 'sont retournés sans qu'aucune erreur ne soit déclenchée. Peut-être que copy2 ne supporte pas le multithreading (mais je m'en suis sorti en l'utilisant car mes fichiers de test étaient très petits). Pour copier le même fichier à plusieurs endroits, changez 'copy_file()' pour accepter un autre argument 'dst_dir', puis appelez-le plusieurs fois, une fois pour chacune des destinations. – martineau

+0

Merci beaucoup. – trench