用python利用进程池也一个复制文件夹的小程序

import os
import hashlib
from multiprocessing import Pool
from multiprocessing import Manager


def innerCopyFile(fileName, srcPath, destPath, q):
    """
    拷贝一个文件
    """
    # 拼出源文件的绝对路径和目标文件的绝对路径
    srcFileName = srcPath + '/' + fileName
    destFileName = destPath + '/' + fileName

    # 打开源文件,写入到目标文件
    with open(srcFileName, 'rb') as fr:
        with open(destFileName, 'wb') as fw:
            for i in fr:
                fw.write(i)
    q.put(fileName)  # 向进程池的队列中,放入当前拷贝完成的文件名

    return True
# 测试单个文件是否可以传输
# copyFile("httpserver.png", "httpserver2.png")


def copyFile(fileName, srcPath, destPath, q):
    # 如果源文件夹不存在,则报错,然后退出操作
    if not os.path.exists(srcPath):
        print("strPath %s is not exists." % srcPath)
        return None

    # 如果目标文件夹不存在,则创建一个文件夹
    if not os.path.exists(destPath):
        try:
            os.mkdir(destPath)
        except:
            print("mkdir %s error" % destPath)
            return None

    # 真正的拷贝文件操作
    return innerCopyFile(fileName, srcPath,
                         destPath, q)

CHUCKSIZE = 4096

# 给文件做HASH的函数
def hashFile(fileName):
    h = hashlib.sha256()
    with open(fileName, 'rb') as f:
        while True:
            chunk = f.read(CHUCKSIZE)
            if not chunk:
                break
            h.update(chunk)
    return h.hexdigest()

if __name__ == "__main__":
    # 接受用户输入的文件目录,同时产生一个副本目录
    srcPath = input("请输入您要拷贝的文件目录:")
    destPath = srcPath + "-副本"

    # 如果目标文件夹已经存在的情况下,怎么处理,
    # 注意这里不能覆盖
    while os.path.isdir(destPath):
        destPath = destPath + "-副本"

    # 如果源文件夹不存在,则报错,然后退出操作
    if not os.path.exists(srcPath):
        print("strPath %s is not exists." % srcPath)

    # 如果目标文件夹不存在,则创建一个文件夹
    if not os.path.exists(destPath):
        try:
            os.mkdir(destPath)
        except:
            print("mkdir %s error" % destPath)

    # 记录当前需要拷贝的文件夹下的文件及其个数
    allFileNames = os.listdir(srcPath)
    allNum = len(allFileNames)
    num = 0  # 记录当前完成拷贝的文件个数

    # 创建进程池
    p = Pool()
    q = Manager().Queue()  # 进程池通信需要的队列

    # 拷贝文件夹的操作
    for i in allFileNames:
        p.apply_async(func=copyFile, args=(i, srcPath, destPath, q))
    p.close()

    while num < allNum:
        fileName = q.get()  # 如果get不到信息,这里会阻塞

        num += 1
        rate = num / allNum * 100  # 获取当前的进度

        # 做文件的HASH值检验
        srcFileName = srcPath + '/' + fileName
        destFileName = destPath + '/' + fileName

        if (hashFile(srcFileName) == hashFile(destFileName)):
            print("%s copied ok" % srcFileName)
        else:
            print("%s copied failed" % srcFileName)

        print("Current rate is %.1f%%" % rate)

    # 等待进程池的操作
    p.join()
    print("复制完成")

这样就完成了一个复制文件夹的程序,可以运行输入要复制文件的路径测试

猜你喜欢

转载自blog.csdn.net/wjun0707/article/details/81204979