下图是《Python程序设计开发宝典》第330页例12-7的代码,本意是使用多线程技术进行文件复制,重点演示嵌套函数定义、多线程编程技术以及队列在多线程同步时的用法。
在代码中,使用内嵌函数add()创建一个线程负责往队列q中添加要复制的文件和文件夹名称,使用内嵌函数copy()创建多个线程负责从队列q中获取这些名字并进行真正的复制或创建,使用队列q实现这些线程之间的通信和同步。
在这个例子中,add()函数对应的一个线程相当于生产者,copy()对应的多个线程相当于消费者,队列q相当于缓冲池用于平衡生产者和消费者之间的速度。
在add()函数中,原意是递归把指定路径src及其所有子文件夹中的文件名和子文件夹名都依次放入队列q,最后再往队列q中写入num(copy线程的数量)个空值None,这些空值的唯一作用是用于copy线程识别并结束工作状态。
在上面的代码中,add()函数在往q中逐个追加要复制的文件名和文件夹名时使用了递归,这本身并没有什么问题,问题在于最后往q中写入空值None的代码也在add()函数之内。由于add函数是递归调用的,导致这段写入None的代码被执行多次,而队列q的大小有限,队列满了之后导致了线程阻塞。执行该程序时,如果参数src中没有子文件夹则运行正常,如果参数src中有子文件夹则程序无法正常结束。
解决这个问题的方法有多种,这里给出比较简单的一种。在《Python程序设计开发宝典》283页“第10章 文件与文件夹操作”讲解遍历目录树时,给出了按深度优先遍历和按广度优先遍历两种方法。参考按广度优先遍历目录树的思路,把例330页12-7代码中add()函数改写为下面的样子,就可以解决这个bug了。
公众号“Python小屋”,
标签:12,函数,Python,代码,队列,add,文件夹,线程,bug From: https://blog.51cto.com/u_9653244/6454792