我是多处理的新手,我只是想在Python 3.2中编写一个简单的程序,它在一个线程中有一个无限增加的计数器,而第二个线程检查是否已经在一个线程中达到一个给定的值。第一个帖子。达到该值后,我希望关闭多处理线程,并让程序显示“Process Complete”语句。
据我了解,该程序看起来像(给定值为10):
import multiprocessing as mp
def Counter():
i=1
while i > 0:
print("i: ",i)
i+=1
def ValueTester(i):
if i >= 10:
*End Counter Function Thread*
if __name__ == '__main__':
*Begin multiprocessing, one thread for "Counter" and a second for "ValueTester"*
print("Process Complete")
我为伪代码的含糊不清道歉;我已经阅读了Python文档以及几个不同的示例,我似乎无法找到一个简单的解决方案。
此外,一旦这个工作,我将如何设置给定的停止值(即将变量传递给ValueTester
,而不是仅使用10
)?
非常感谢你的帮助。
答案 0 :(得分:4)
我们需要注意在线程和进程之间做出明确区分。
线程都在相同的进程下运行。可以共享访问的值
线程之间。安全(协调)中的线程可以更改值
只有当值在threading.Lock
之前受到保护时才会使用
改变。在CPython中,最常见的Python实现和PyPy,但是
与其他实现相比,如Jython或Iron Python,GIL(全球
解释器锁)防止多个线程在任何给定的情况下运行
时间。所以在CPython下,多个线程实际上是串行运行的,而不是
同时。尽管如此,多线程对于I / O关注工作仍然有用
作为查询许多网站,因为大部分时间都在等待
用于网络(I / O)活动。因此多线程不必等待
同样,与任务相比,争取访问单个CPU
像数学计算一样是CPU密集型的。
现在说了这么多,你正在处理多个进程,而不是 线程。流程彼此独立。他们可以并且确实可以运行 同时在多个CPU上(如果可用)(包括在CPython下)。当你 生成一个进程,将全局值从原始进程复制到 产生的过程。在某些操作系统上,比如Linux,它们具有“写时复制”功能 实际上,在进程尝试进行之前,进程之间会共享值 覆盖一个值,此时该值被复制为独立于 另一个过程。因此,当您修改值时,两个进程最终会有两个 变量名称相同但可以具有完全不同的值。
多处理模块提供了特殊对象以方便使用
sharing state between processes。其中包括mp.Value
,mp.Array
,
mp.Manager
。请注意,当您使用这些对象时you must also use a mp.Lock
防止一个进程更改值,而另一个进程尝试执行相同操作
事情。但是,Lock也会减慢进程,因为必须等待
锁定被释放。
现在,当在另一个流程中达到条件时发出流程信号,请使用mp.Event
:
import multiprocessing as mp
import time
def Counter(i, event, lock):
with lock:
i.value = 1
while i.value > 0 and not event.is_set():
print("i: ", i.value)
with lock:
i.value += 1
def ValueTester(i, stopval, event):
while True:
if i.value >= stopval:
event.set()
break
else:
time.sleep(0.1)
if __name__ == '__main__':
num = mp.Value('d', 0.0)
# A lock is not absolutely necessary here since only one process modifies
# num, but I'm including it since it is necessary (to avoid race conditions)
# in the more usual case when multiple processes may modify num.
lock = mp.Lock()
event = mp.Event()
counter = mp.Process(target=Counter, args=(num, event, lock))
counter.start()
tester = mp.Process(target=ValueTester, args=(num, 10, event))
tester.start()
tester.join()
counter.join()
print("Process Complete")
有关如何使用多处理的更多示例,请参阅Doug Hellman's Python Module of the Week tutorial。
答案 1 :(得分:1)
所以你需要的是两个线程(进程)相互通信的机制。幸运的是,Python的多处理模块为您提供了一些选项,其中一个是队列。
所以要做的第一件事就是启动这两个def,然后传入一个可以用来进行通信的共享队列。由于您希望主进程终止子进程,因此第一个进程应该从第二个进程开始。
import multiprocessing as mp
from multiprocessing import Queue
def counter(): #use lowercase c, 'Counter' is importable
threshold = 10
output = Queue(1) #for placing numbers on the queue
input = Queue(1) #for looking for the signal that child is done
child = Process(target=valuetester, args=(threshold, output, input))
child.start()
i=1
while i > 0:
output.put(i)
print("i: ",i)
i+=1
try:
done = input.get_nowait()
if done == 'Im Done!':
print 'Process Complete!'
child.join() #clean up the child proc
return
except Empty:
pass #input is empty, no big deal
def valuetester(threshold, input, output):
thresholdNotPassed = False
while thresholdNotPassed:
i = input.get()
if i >= threshold:
output.put('Im Done!')
return
else:
pass #nothing to do... just wait
#Start the counter proc. You could use the main process since its easier
if __name__ == 'main':
counter()
有几点需要注意: 我让队列的maxsize为1 ...如果队列已满,这将会阻塞(保持在该行)。
你可以看到我还使用get_nowait()为主进程检查子进程是否已完成,否则使用普通get
会阻塞,我们会死锁!