3

我有这个功能试图打印额外的'。' 每秒将一个大文件夹(~3GB)从一个地方复制到另一个地方:

def copy_folder(source, destination):
    print 'copying',
    while shutil.copytree(src=source, dst=destination):
        print '.',
        time.sleep(1)

但是当我调用函数时:

source = 'source_folder'
destination = 'destination_folder'
copy_folder(source=source, destination=destination)

它可以很好地复制整个文件夹,但不会打印“。” 一点也不。

我需要使用线程吗?

4

4 回答 4

4

Python中的线程非常简单:

import sys, shutil, time, threading

class CopyThread(threading.Thread):
    def __init__(self, source, destination):
        super(CopyThread, self).__init__()

        self.source = source
        self.destination = destination

    def run(self):
        time.sleep(5)  # Delete me later on, I'm just here to slow things down
        return shutil.copytree(src=self.source, dst=self.destination)

if __name__ == '__main__':
    thread = CopyThread('source_folder', 'destination_folder')
    thread.start()

    while thread.is_alive():
        sys.stdout.write('.')
        sys.stdout.flush()

        time.sleep(1)

    thread.join()

只是子类threading.Thread和覆盖run()。之后,调用.start()该类的一个实例,你就有了一个线程。

于 2012-08-21T02:42:57.483 回答
1

copytree 将复制整个树,因此在复制完成并且可以评估返回值之前,while 循环不会运行。

我的 python 生锈了,但我会给出一个如何实现线程的想法(受此处找到的代码的启发)。

def copy_folder(source, destination):
    self.iscopying = True        
    self.thread = threading.Thread(name="GPS Data", target=self.thread_run)
    self.thread.setDaemon(True)
    self.thread.start()
    shutil.copytree(src=source, dst=destination)
    self.iscopying = false


def thread_run(self):
    while self.iscopying:
        print '.'
        time.sleep(1)

本质上,创建一个标志,告诉线程何时发生复制,然后在复制完成时将其设置为 false。

于 2012-08-21T02:28:27.700 回答
1

看copytree源码,核心就是这个循环:

for name in names:
   if name in ignored_names:
       continue
   srcname = os.path.join(src, name)
   dstname = os.path.join(dst, name)
   try:
       if symlinks and os.path.islink(srcname):
           linkto = os.readlink(srcname)
           os.symlink(linkto, dstname)
       elif os.path.isdir(srcname):
           copytree(srcname, dstname, symlinks, ignore)
       else:
           # Will raise a SpecialFileError for unsupported file types
           copy2(srcname, dstname)
   # catch the Error from the recursive copytree so that we can
   # continue with other files
   except Error, err:
       errors.extend(err.args[0])
   except EnvironmentError, why:
       errors.append((srcname, dstname, str(why)))

如果您yield在最后添加一个权利,您的循环将起作用 - 但您将在复制每个文件或目录后打印,而不是按时间间隔打印(您time.sleep会在副本之间发生,只是让整个事情花费更长的时间;因为每个时间间隔,是的,您将需要线程)。但是,如果您愿意,这也将允许您提供更详细的反馈 - 例如,您可以yield name(或,yield (srcname, destname))能够打印有关复制文件的反馈。

于 2012-08-21T02:47:47.707 回答
0

我不知道有一个模块可以异步执行此操作...并不是说没有...但是您可以递归地浏览文件夹并打印“。” 在每个文件/文件夹之后

于 2012-08-21T02:36:10.197 回答