如何在Python中获取文件移动进度?
我有一个小脚本,用来整理我下载的文件,效果很好。不过,我想在移动大文件的时候,能看到进度,比如显示一个进度条或者百分比。目前我做的方式是:
print "moving..."
os.renames(pathTofile, newName)
print "done"
但我希望能看到类似进度条([..... ]这种样子)或者百分比直接打印到控制台上。
我不需要任何图形界面,只想要最简单、最省事的方法来显示操作进度。
谢谢!
3 个回答
0
这个例子的方法是在Benno的回答基础上进行扩展的,它通过估算剩余时间,并在复制完成后移除进度条。
def copy_large_file(src, dst):
'''
Copy a large file showing progress.
'''
print('copying "{}" --> "{}"'.format(src, dst))
# Start the timer and get the size.
start = time.time()
size = os.stat(src).st_size
print('{} bytes'.format(size))
# Adjust the chunk size to the input size.
divisor = 10000 # .1%
chunk_size = size / divisor
while chunk_size == 0 and divisor > 0:
divisor /= 10
chunk_size = size / divisor
print('chunk size is {}'.format(chunk_size))
# Copy.
try:
with open(src, 'rb') as ifp:
with open(dst, 'wb') as ofp:
copied = 0 # bytes
chunk = ifp.read(chunk_size)
while chunk:
# Write and calculate how much has been written so far.
ofp.write(chunk)
copied += len(chunk)
per = 100. * float(copied) / float(size)
# Calculate the estimated time remaining.
elapsed = time.time() - start # elapsed so far
avg_time_per_byte = elapsed / float(copied)
remaining = size - copied
est = remaining * avg_time_per_byte
est1 = size * avg_time_per_byte
eststr = 'rem={:>.1f}s, tot={:>.1f}s'.format(est, est1)
# Write out the status.
sys.stdout.write('\r{:>6.1f}% {} {} --> {} '.format(per, eststr, src, dst))
sys.stdout.flush()
# Read in the next chunk.
chunk = ifp.read(chunk_size)
except IOError as obj:
print('\nERROR: {}'.format(obj))
sys.exit(1)
sys.stdout.write('\r\033[K') # clear to EOL
elapsed = time.time() - start
print('copied "{}" --> "{}" in {:>.1f}s"'.format(src, dst, elapsed))
你可以在这里看到一个完整的可运行版本:https://gist.github.com/jlinoff/0f7b290dc4e1f58ad803。
8
你不能通过 os.renames 来获取那种信息。最好的办法是自己写一个文件复制的操作,但在复制之前先用 stat 来查看文件的完整大小,这样你就能知道自己复制到哪儿了。
可以参考下面的代码:
source_size = os.stat(SOURCE_FILENAME).st_size
copied = 0
source = open(SOURCE_FILENAME, 'rb')
target = open(TARGET_FILENAME, 'wb')
while True:
chunk = source.read(32768)
if not chunk:
break
target.write(chunk)
copied += len(chunk)
print '\r%02d%%' % (copied * 100 / source_size),
source.close()
target.close()
不过要注意,这种方法可能会比使用 os.rename 慢很多。
1
其实没有办法显示进度条,因为“重命名”这个操作在系统中只是一条简单的命令。
需要注意的是,只有当你要移动的文件在不同的物理存储设备上时,这个“重命名”操作才会花时间。如果它们在同一个设备上,重命名几乎是瞬间完成的。如果你知道自己是在不同的存储设备之间复制数据,可能可以使用一些来自shutil模块的函数,比如copyfileobj
。虽然没有现成的进度监控功能,但你可以自己实现一个类似文件的对象来跟踪进度。