我的结构(大规模简化)如下所示:
import multiprocessing
def creator():
# creates files
return
def relocator():
# moves created files
return
create = multiprocessing.Process(target=creator)
relocate = multiprocessing.Process(target=relocator)
create.start()
relocate.start()
我要做的是,creator
和创建的一堆文件一旦创建,就会被relocator
移动到另一个目录。< / p>
我想在这里使用multiprocessing
的原因是:
creator
等待移动首先完成,因为移动需要时间我不想浪费。我希望creator
和relocator
进程都是串行的(每次一个文件)但是并行运行。行动的“日志”应该像这样:
# creating file 1
# creating file 2 and relocating file 1
# creating file 3 and relocating file 2
# ...
# relocating last file
根据我所读到的内容,Queue
是前往此处的方式。
策略(也许不是最好的?!)
创建文件后,它将进入队列,在完成重定位后,它将从队列中删除。
然而,我遇到了编码问题;同时创建多个文件(并行运行creator
的多个实例)和其他...
我会非常感谢任何想法,提示,解释等
答案 0 :(得分:1)
让我们把你的想法分解为这个功能:
创作者应该创建文件(例如100个)
重定位器应一次移动1个文件,直到没有其他文件可以移动
创作者可以在 Relocator 之前结束,所以它也可以 把自己变成一个 Relocator 两者都要知道什么时候去 完成
因此,我们有两个主要功能:
def create(i):
# creates files and return outpath
return os.path.join("some/path/based/on/stuff", "{}.ext".format(i))
def relocate(from, to):
# moves created files
shuttil.move(from, to)
现在让我们创建我们的流程:
from multiprocessing import Process, Queue
comm_queue = Queue()
#process that create the files and push the data into the queue
def creator(comm_q):
for i in range(100):
comm_q.put(create(i))
comm_q.put("STOP_FLAG") # we tell the workers when to stop, we just push one since we only have one more worker
#the relocator works till it gets an stop flag
def relocator(comm_q):
data = comm_q.get()
while data != "STOP_FLAG":
if data:
relocate(data, to_path_you_may_want)
data = comm_q.get()
creator_process= multiprocessing.Process(target=creator, args=(comm_queue))
relocators = multiprocessing.Process(target=relocator, args=(comm_queue))
creator_process.start()
relocators .start()
这样我们现在就拥有了一个创建者和一个重定位器,但是,现在我们要让 Creator 在创建作业完成时开始重定位,我们可以使用relocator,但是我们需要再推一个"STOP_FLAG"
,因为我们将有2个进程重新定位
def creator(comm_q):
for i in range(100):
comm_q.put(create(i))
for _ in range(2):
comm_q.put("STOP_FLAG")
relocator(comm_q)
让我们说我们现在需要任意数量的重定位器进程,我们应该调整一下我们的代码来处理这个问题,我们需要creator
方法知道有多少标志通知其他进程何时到停止,我们生成的代码看起来像这样:
from multiprocessing import Process, Queue, cpu_count
comm_queue = Queue()
#process that create the files and push the data into the queue
def creator(comm_q, number_of_subprocesses):
for i in range(100):
comm_q.put(create(i))
for _ in range(number_of_subprocesses + 1): # we need to count ourselves
comm_q.put("STOP_FLAG")
relocator(comm_q)
#the relocator works till it gets an stop flag
def relocator(comm_q):
data = comm_q.get()
while data != "STOP_FLAG":
if data:
relocate(data, to_path_you_may_want)
data = comm_q.get()
num_of_cpus = cpu_count() #we will spam as many processes as cpu core we have
creator_process= Process(target=creator, args=(comm_queue, num_of_cpus))
relocators = [Process(target=relocator, args=(comm_queue)) for _ in num_of_cpus]
creator_process.start()
for rp in relocators:
rp.start()
然后你必须等待才能完成:
creator_process.join()
for rp in relocators:
rp.join()
您可以查看multiprocessing.Queue
documentation
特别是get
method(默认情况下是阻止调用)
从队列中删除并返回一个项目。如果是可选的args块 True(默认值),超时为None(默认值),阻止if 必要的,直到一个项目可用。