Bonjour,
Il est clair que la bonne solution est d'analyser le code Python du module shutil, d'en extraire les parties utiles et d'ajouter ce qui manque, c'est-à-dire le callback pendant la copie par bloc. On apprend d'ailleurs beaucoup de chose de cette façon là. En particulier pour tenir compte du caractère multi-plateforme de Python (Windows-Linux-MacOSX).
Voilà cependant à titre d'exemple un petit code qui peut faire le boulot dans un cas très simplifié: uniquement Windows, sans transfert des droits ni de vérification de validité des données (ex: ça plantera si les données ne sont pas valides):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| # Python 2
import os
def copiefichier(ficsource, ficdestin, lgbuf=8192, callback=None):
"""Copie le contenu du fichier source vers le fichier destination
"""
if os.path.isdir(ficdestin):
# la destination étant un répertoire, on lui ajoute le nom source
ficdestin = os.path.join(ficdestin, os.path.basename(ficsource))
with open(ficsource, 'rb') as fs:
with open(ficdestin, 'wb') as fd:
while True:
buf = fs.read(lgbuf)
if buf == "":
break # plus rien à copier: on a fini
fd.write(buf)
if callback!=None:
callback(buf) # envoi du buffer au callback si demandé |
On voit le principe: on ouvre les 2 fichiers en binaire (l'un en lecture et l'autre en écriture) et on transfère des blocs d'octets par l'intermédiaire d'un buffer dont on peut d'ailleurs modifier la taille (8192 octets ici).
Le callback est le nom de la fonction qui peut recevoir le contenu du buffer à chaque fois qu'il est copié. On n'est bien sûr pas obligé d'en donner un.
Voilà un exemple de progression. on utilise une classe pour pouvoir afficher le pourcentage:
1 2 3 4 5 6 7 8 9 10
| class Progression(object):
def __init__(self, lgtotal):
self.lgtotal = lgtotal
self.lgcopie = 0
def __call__(self, buf):
self.lgcopie += len(buf)
pourc = 1.0*self.lgcopie/self.lgtotal*100
print "%.1f %%" % (pourc) |
Et voilà comment on utilise:
1 2 3 4 5 6 7 8 9
| ficsource = r"E:\Python34\DLLs\sqlite3.dll"
ficdestin = r"E:\Temp"
# on initialise la classe Progression et on lui passe comme argument la taille totale du fichier à copier (pour avoir les % !)
progression = Progression(os.path.getsize(ficsource))
# et on lance la copie en citant le callback à utiliser:
copiefichier(ficsource, ficdestin, callback=progression) |
Ce qui donne pour cet exemple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| 1.6 %
3.3 %
4.9 %
6.6 %
8.2 %
9.9 %
11.5 %
13.2 %
14.8 %
16.5 %
18.1 %
19.8 %
21.4 %
23.0 %
24.7 %
26.3 %
28.0 %
29.6 %
31.3 %
32.9 %
34.6 %
36.2 %
37.9 %
39.5 %
41.2 %
42.8 %
44.4 %
46.1 %
47.7 %
49.4 %
51.0 %
52.7 %
54.3 %
56.0 %
57.6 %
59.3 %
60.9 %
62.6 %
64.2 %
65.8 %
67.5 %
69.1 %
70.8 %
72.4 %
74.1 %
75.7 %
77.4 %
79.0 %
80.7 %
82.3 %
84.0 %
85.6 %
87.2 %
88.9 %
90.5 %
92.2 %
93.8 %
95.5 %
97.1 %
98.8 %
100.0 % |
[edit] pour adapter le 1er code à Python 3, il faut remplacer la ligne < if buf == "": > par < if len(buf)==0: >
Partager