Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过函数调用与Python3.4多处理中的进程通信_Python_Python Multiprocessing - Fatal编程技术网

通过函数调用与Python3.4多处理中的进程通信

通过函数调用与Python3.4多处理中的进程通信,python,python-multiprocessing,Python,Python Multiprocessing,我创建了一个新类,它是multiprocessing.Process的子类,我想调用这个类上的方法。这些方法更改类成员,但不接受参数,我认为应该透明地工作。例如,在下面的MWE中,我创建了一个从Process继承的类,它有一个stop()函数,该函数只设置一个实例成员标志。设置此标志时,run()方法似乎没有注意到更改。当我从线程继承时,这一切似乎都起作用了。线程,思想 from queue import Empty import multiprocessing class Worker(m

我创建了一个新类,它是multiprocessing.Process的子类,我想调用这个类上的方法。这些方法更改类成员,但不接受参数,我认为应该透明地工作。例如,在下面的MWE中,我创建了一个从Process继承的类,它有一个stop()函数,该函数只设置一个实例成员标志。设置此标志时,run()方法似乎没有注意到更改。当我从线程继承时,这一切似乎都起作用了。线程,思想

from queue import Empty
import multiprocessing


class Worker(multiprocessing.Process):
    def __init__(self, queue):
        multiprocessing.Process.__init__(self) # , daemon=True)
        self.queue = queue
        self.close = False

    def stop(self):
        self.close = True
        print(self.close)

    def run(self):
        while (not self.close) or self.queue.qsize() > 0:
            print(self.close)
            print(self.queue.qsize())
            for item in range(0, self.queue.qsize()):
                try:
                    self.queue.get_nowait()
                except Empty:
                    continue

queue = multiprocessing.Queue()
dbq = Worker(queue)
dbq.start()
queue.put("d")
dbq.stop()
dbq.join()

您必须使用类似的方法来实现进程之间的同步

示例代码:

from queue import Empty
from ctypes import c_bool
import multiprocessing

class Worker(multiprocessing.Process):
    def __init__(self, queue):
        multiprocessing.Process.__init__(self) # , daemon=True)
        self.queue = queue
        self.close = multiprocessing.Value(c_bool, False)

    def stop(self):
        self.close.value = True
        print(self.close)

    def run(self):
        while (not self.close.value) or self.queue.qsize() > 0:
            print(self.close)
            print(self.queue.qsize())
            for item in range(0, self.queue.qsize()):
                try:
                    self.queue.get_nowait()
                except Empty:
                    continue

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    dbq = Worker(queue)
    dbq.start()
    queue.put("d")
    dbq.stop()
    dbq.join()

进程不像线程那样与其父进程共享内存空间。当一个进程被
fork
ed时,它将获得父进程内存的一个新副本,因此您不能像与线程一样轻松地共享(实际上……实际上是这样的)

我建议,为了杀死工人,您可以使用一个同步原语,比如,因为通常工人会一起被杀死,以响应所发生的事情

您将得到类似的结果(注意,对于工人,没有
stop
方法):


使用同步对象而不仅仅是基本类型来执行任何进程间通信。我推荐multiprocessing.eventThank,我想保持我的api不变,所以使用这种方法似乎应该有效。我感谢您的解释。我不明白在我的原始代码中调用stop()时发生了什么。我们在multiprocessing.Process子进程上调用start(),它会分叉,但是为什么不在新进程中调用此对象上的函数呢?我以为这些方法会通过IPC自动封送,比如套接字之类的?因此,稍后对原始对象调用stop()实际上是对代理的调用,代理将使用IPC调用远程对象函数,从而更改远程对象的内存空间?新过程是一个完全不同的内存映射。如果您理解
start
forks,那么您可能理解以后的任何调用都只会影响父进程的内存。这就是为什么需要处理与同步对象的通信。它们是两个进程可以访问的共享内存。谢谢@Reut Sharabani。我认为我所缺乏的是理解为什么父级甚至能够调用从multiprocessing.Process继承的对象上的方法。现在是否有两个Worker实例,一个在父内存空间中,另一个在子进程内存空间中?当我创建对象,然后调用start()时,我在父进程中剩下的“东西”是什么?我认为它是一个代理,在这个代理中,方法被绑定到新子流程中的一个实例。但这似乎不是真的?它只是父对象中没有调用start的对象吗?如果您熟悉任何出现fork的c代码,您就可以很容易地理解为什么这两个代码可以从同一个内存映像开始,但可以转到不同的位置。我不知道Python是如何实现进程的,但我假设您只剩下与父进程对象通信的方法,而子进程继续运行目标函数。
from queue import Empty
import multiprocessing


class Worker(multiprocessing.Process):
    # added the event to the initializing function
    def __init__(self, queue, close_event):
        multiprocessing.Process.__init__(self) # , daemon=True)
        self.queue = queue
        self.close = close_event

    def run(self):
        while (not self.close.is_set()) or self.queue.qsize() > 0:
            print(self.close)
            print(self.queue.qsize())
            for item in range(0, self.queue.qsize()):
                try:
                    self.queue.get_nowait()
                except Empty:
                    continue

queue = multiprocessing.Queue()
# create a shared event for processes to react to
close_event = multiprocessing.Event()
# send event to all processes
dbq = Worker(queue, close_event)
dbq.start()
queue.put("d")
# set the event to stop workers
close_event.set()
dbq.join()