Since there's really no way to programmatically track the progress of rsync, I think your best bet is to "screen scrape" its output and try to "guess" at its progress somehow.
The first thing you should do is use subprocess
instead of commands.getstatusoutput
because you'll get much more control over screen scraping rsync's stdout to track its progress. One solution might be to execute rsync with the -v
option, which will print each file transferred followed by a newline (plus some other cruft that you don't really need). A simple way to guess at the progress of rsync then, would be to do something like:
import subprocess
p = subprocess.Popen(['rsync', '-v', ..other rsync args..], shell=True,
stdout=subprocess.PIPE, close_fds=True)
while p.stdout.readline():
...
# rsync has just "completed" an operation, i.e. it probably
# transferred a file. now would be a good time to update the
# ProgressBar. there are some options here, see below...
...
ret = p.wait()
print "Rsync exited with code %d" % ret
This reads the output of rsync -v ...
one line at a time, and in the while
loop you would update the ProgressBar
as appropriate. The question then becomes, what kind of update? ProgressBar
really has two modes - one that "pings" back and forth indicating progress towards some indeterminate goal, and one that moves the bar from left to right based on an increment towards a known goal.
You could try to "guess" the number of files rsync will transfer by obtaining a file list before hand (with --list-only
or -vn
) and use that as the goal, but this is inherently error-prone because you run the risk of the sender's file list changing in between the time you gather the list and when you actually execute rsync. A better solution is probably just to call pulse()
on the ProgressBar
in the while
loop to indicate that things are happening in the background. If you want to display more information, you could read the output of p.stdout.readline()
and update a gtk.Label
somewhere to indicate which files are being transferred.
(Note: the code above doesn't take into account error conditions when executing rsync, which you should probably do)