2016-05-23 2 views
2

J'ai cherché haut et bas, et chaque fois que je trouve quelque chose qui semble prometteur, il n'est pas sorti. En fin de compte, je veux saisir la progression en temps réel d'une copie de fichier sur une machine Linux depuis Python. Je vais prendre cette progression et l'émettre sur une page web client avec Flask-SocketIO, probablement threadé pour éviter le blocage. Cela ne me dérange pas si c'est rsync, copier, ou tout autre moyen ... (shutil etc) pour gérer la copie réelle. Je veux juste un crochet pour pousser une mise à jour sur le socket. Jusqu'à présent, j'ai trouvé que c'était le plus prometteur. Cependant, je ne comprends pas très bien le mécanisme d'impression de la console, car lorsque j'essaie d'imprimer une sortie dans un fichier, ou simplement une impression Python régulière, elle sort un caractère à la fois.Comment pouvez-vous obtenir la progression de la copie en temps réel d'un gros fichier avec Python?

import subprocess 
import sys 

def copy_with_progress(src, dst): 
    cmd = 'rsync --progress --no-inc-recursive %s %s'%(src, dst) 
    sub_process = subprocess.Popen(cmd, close_fds=True, shell=True, stdout=subproces.PIPE, stderr=subprocess.PIPE) 
    while sub_process.poll() is None: 
     out = sub_process.stdout.read(1) 
     sys.stdout.write(out) 
     sys.stdout.flush() 


src = '/home/user/Downloads/large_file.tar' 
dst = '/media/usbdrive/large_file.tar' 

copy_with_progress(src, dst) 

qui vient de cette question SO: Getting realtime output using subprocess

Toutefois, rapporte la sortie arrière sur stdout. Je voudrais capturer cette sortie dans une variable et l'émettre.

Les progrès stdout ressemble à ceci, avec une ligne mise à jour en permanence: large_file.tar 323.780.608 19% 102.99MB/s 00:00:12 Lorsque j'imprime la variable nommée « out » je reçois un caractère qui imprime à l'écran en faisant défiler une nouvelle ligne encore et encore.

Comment capturer cette information de manière à pouvoir la transmettre au client?

Existe-t-il un moyen de récupérer la ligne entière pour chaque actualisation du statut?

+1

Vous pouvez juste 'stat' le fichier source pour obtenir la taille totale, puis périodiquement' stat' le fichier de destination pour obtenir la taille actuelle tant que le sous-processus est en cours d'exécution. Vous pouvez regarder le paquet 'tqdm' (en mode manuel) pour l'interface utilisateur. – o11c

+0

Vous lisez un octet à la fois, c'est ce que vous attendez –

+0

Comment liriez-vous tous les octets disponibles pour chaque itération de la boucle? –

Répondre

0

Ce que j'ai fait dans le passé est de copier les données dans des morceaux et d'utiliser une fonction de rappel pour surveiller la progression. Quelque chose comme:

# Python_2 

def copy_with_callback(sourceFile, destinationFile, callbackFunction): 
    chunk = 4*1024 
    sourceSize = os.path.getsize(sourceFile) 
    destSize = 0 
    with open(sourceFile, 'rb') as fSrc: 
     with open(destinationFile, 'wb') as fDest: 
      data = fSrc.read(chunk) 
      if len(data) == 0: 
       break 
      fDest.write(data) 
      destSize += len(data) 
      callbackFunction(sourceSize, destSize) 

def example_callback_function(srcSize, dstSize): 
    ''' Just an example with print. Your viewer code will vary ''' 
    print 'Do something with these values:', srcSize, dstSize 
    print 'Percent?', 100.0 * dstSize/srcSize 

def main(): 
    src = '/tmp/A/path/to/a/file.txt' 
    dest = '/tmp/Another/path/to/a/file.txt' 
    copy_with_callback(src, dest, example_callback_function) 

Un avantage est ce code python ne dépend pas de système d'exploitation des fonctionnalités spécifiques.

+0

Super idée! Merci! –