苏瓦奥术 发表于 2020-7-31 19:31:51

多线程复制文件,在线程启动时出现了问题

import os
import hashlib
from threading import Thread, Lock
import time

ORIGIN_PATH = r'F:\Python\拷贝\test1'
TARGET_PATH = r'F:\Python\拷贝\test2'

all_filename = os.listdir(ORIGIN_PATH)
# print(all_filename)
th_ls = []
lock = Lock()
count = 0
ls = []

pro = []

CHUNKSIZE = 4096    # 每次读取文件的字节数
def copy_hashFile(filename,path=None, write_filename=None):
    '''
    对文件做hash
    '''
    def myCopy():
      # 以二进制的形式在文件末尾追加写入
      with open(path + os.sep + write_filename, 'ab') as f:
            f.write(chunk)
    h = hashlib.sha256()
    with open(filename, 'rb') as f:
      while True:
            chunk = f.read(CHUNKSIZE)
            if not chunk:   # 当读文件到结尾处时,跳出循环
                pro.append(filename)
                break
            h.update(chunk)
            if path:
                # 开始循环写入文件
                myCopy()
    return h.hexdigest()    # 得到文件最终的hash值

def main():
    global count
    while True:
      if not all_filename:
            os._exit(0)
      with lock:
            filename = all_filename.pop()
      # print(filename)
      # 在目标文件夹下创建一个空文件
      # print(ORIGIN_PATH + os.sep + filename)
      with open(TARGET_PATH + os.sep + filename, 'w'):
            pass
      # 获得原文件hash值并将其复制到目标文件夹下
      hash_number1 = copy_hashFile(ORIGIN_PATH + os.sep + filename, TARGET_PATH, filename)
      # 获得复制后的hash值
      hash_number2 = copy_hashFile(TARGET_PATH + os.sep + filename)
      
      # 比较hash值
      if hash_number1 == hash_number2:
            with lock:
                count += 1
            print(str(count) + '' + filename + '文件复制成功')
      else:
            with lock:
                count += 1
                ls.append(filename)
            print(str(count) + '' + filename + '文件复制失败')



for _ in range(20):
    th = Thread(target=main)
    th_ls.append(th)

# 不清楚为什么
# 只有sleep 1秒以上后才不会出错
for each in th_ls:
    each.start()
    time.sleep(5)


while True:
    # print(not all_filename)
    # time.sleep(1.5)
    if not all_filename:
      for each in th_ls:
            each.join()


代码如上,我之前在复制测试文件的时候,一直有几个文件无法复制,在添加了sleep(1)后才成功,后来复制更多更大的文件后,复制的成功率随着sleep的时间增加而增加,这是为什么呢?
求大佬{:5_92:} !

苏瓦奥术 发表于 2020-8-1 00:08:09

发现了问题所在了,是那个os._exit(0)导致的,这行代码还会导致线程无法回收,改成break就行了。
唉,事实证明Python的多线程IO还是比不过单线程,单线程的代码比这快多了

°蓝鲤歌蓝 发表于 2020-8-1 06:34:10

读写文件这种 磁盘 io 用多线程是会快一些的,慢了说明哪里用的不对。

陈尚涵 发表于 2020-8-3 18:09:10

对啊,这一般都用多线程
页: [1]
查看完整版本: 多线程复制文件,在线程启动时出现了问题