Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/183.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
Python 在多进程之间传递方法返回值。进程实例_Python_Multiprocessing - Fatal编程技术网

Python 在多进程之间传递方法返回值。进程实例

Python 在多进程之间传递方法返回值。进程实例,python,multiprocessing,Python,Multiprocessing,如何从另一个multiprocessing.Process实例中的方法获取返回值? 我有两个文件: 文件hwmgr.py: import multiprocessing as mp from setproctitle import setproctitle import smbus import myLoggingModule as log class HWManager(mp.Process): def __init__(self): mp.Process.__ini

如何从另一个multiprocessing.Process实例中的方法获取返回值?

我有两个文件:

文件hwmgr.py:

import multiprocessing as mp
from setproctitle import setproctitle
import smbus
import myLoggingModule as log

class HWManager(mp.Process):
    def __init__(self):
        mp.Process.__init__(self, cmd_q, res_q)
        self.i2c_lock = mp.Lock()
        self.commandQueue = cmd_q
        self.responseQueue = res_q
    def run(self):
        setproctitle('hwmgr')
        while True:
            cmd, args = self.commandQueue.get()
            if cmd is None: self.terminate()
            method = self.__getattribute__(cmd)
            result = method(**args)
            if result is not None:
                self.responseQueue.put(result)

    def get_voltage(self):
        with self.i2c_lock:
            # ...do i2c stuff to get a voltage with smbus module
        return voltage
文件main.py:

import multiprocessing as mp
import hwmgr

cmd_q = mp.Queue()
res_q = mp.Queue()

hwm = hwmgr.HWManager(cmd_q, res_q)
hwm.start()

cmd_q.put(('get_voltage', {}))
battery = res_q.get()

print battery
虽然此解决方案有效,但HWManager流程的复杂性在将来可能会增加,其他流程也会从main.py(代码简化)派生出来,它们使用相同的机制。显然,错误的进程有可能从其
res_q.get()
命令中获取错误的返回数据

有什么更可靠的方法可以做到这一点?
(我试图避免每个进程都有一个return
mp.Queue
,因为这需要每次重新处理HWManager类以适应额外的队列)

确定-在制品代码如下:

hwmgr.py:

import multiprocessing as mp
from setproctitle import setproctitle
import smbus
import myLoggingModule as log

class HWManager(mp.Process):
    def __init__(self):
        mp.Process.__init__(self, cmd_q, res_q)
        self.i2c_lock = mp.Lock()
        self.commandQueue = cmd_q
        self.responseQueue = res_q
    def run(self):
        setproctitle('hwmgr')
        while True:
            cmd, args = self.commandQueue.get()
            if cmd is None: self.terminate()
            method = self.__getattribute__(cmd)
            result = method(**args)
            if result is not None:
                self.responseQueue.put(result)

    def get_voltage(self):
        with self.i2c_lock:
            # ...do i2c stuff to get a voltage with smbus module
        return voltage
import multiprocessing as mp
from multiprocessing.connection import Listener
from setproctitle import setproctitle
import smbus

class HWManager(mp.Process):
    def __init__(self):
        mp.Process.__init__(self)
        self.i2c_lock = mp.Lock()

    def run(self):
        setproctitle('hwmgr')
        self.listener = Listener('/tmp/hw_sock', 'AF_UNIX')

        with self.i2c_lock:
            pass  # Set up I2C bus to take ADC readings

        while True:
            conn = self.listener.accept()
            cmd, args = conn.recv()

            if cmd is None: self.terminate()
            method = self.__getattribute__(cmd)
            result = method(**args)
            conn.send(result)

    def get_voltage(self):
        with self.i2c_lock:
            voltage = 12.0  # Actually, do i2c stuff to get a voltage with smbus module

        return voltage
文件client.py

import multiprocessing as mp
from multiprocessing.connection import Client
from setproctitle import setproctitle
from time import sleep

class HWClient(mp.Process):

def __init__(self):
    mp.Process.__init__(self)
    self.client = Client('/tmp/hw_sock', 'AF_UNIX')

def run(self):
    setproctitle('client')
    while True:
        self.client.send(('get_voltage', {}))
        battery = self.client.recv()
        print battery
        sleep(5)
main.py:

import hwmgr
import client

cl = client.HWClient()  # Put these lines here = one error (conn refused)
cl.start()
hwm = hwmgr.HWManager()
hwm.start()
# cl = client.HWClient()  # ...Or here, gives the other (in use)
# cl.start()

这听起来好像需要一个标准的客户机-服务器体系结构。您可以使用UNIX域套接字(或Windows上的命名管道)。多处理模块使在进程之间传递python对象变得非常容易。服务器代码的示例结构:

from multiprocessing.connection import Listener

listener = Listener('somefile', 'AF_UNIX')

queue = Queue()
def worker():
    while True:
        conn, cmd = queue.get()
        result = execute_cmd(cmd)
        conn.send(result)
        queue.task_done()


for i in range(num_worker_threads):
     t = Thread(target=worker)
     t.daemon = True
     t.start()


while True:
    conn = listener.accept()
    cmd = conn.recv()
    queue.put((conn, cmd)) # Do processing of the queue in another thread/process and write result to conn
客户端看起来像:

from multiprocessing.connection import Client
client = Client('somefile', 'AF_UNIX')

client.send(cmd)
result = client.recv()

上面的代码使用线程作为辅助对象,但是您也可以使用多处理模块轻松地为辅助对象创建进程。有关详细信息,请参阅。

您的情况有点混乱。如果您需要进程之间进行对话,而不包括其他进程,那么每个进程之间的队列或管道是可以的,但您似乎想要广播。在这种情况下,我将编写一个PubSub类型的系统,您可以将消息广播到该系统,在这种情况下,其他进程将接收所有消息,但可以设置为只响应它们关心的消息。在这种情况下,每个子进程都会订阅他们关心的发布者。这可以通过管道或共享对象从管理器对象中关闭。它的实际应用是一个硬件管理器进程,用于控制对硬件资源的访问。上面的机制只显示了另一个想要获取I2C数据的进程(在本例中为“主”进程)。例如,另一个派生的进程可能会请求切换中继,返回的值将是成功/失败的T/F。常见的进程是硬件管理器,它可以在单个mp.队列上接收命令,但返回值会到达不同的位置。我不想每次有新进程请求服务时都重写HWManager,只是为了提供一个新的返回队列。因此,我将用代码替换
Queue.append((conn,cmd))
,以便在“服务器”中运行方法?如果两个进程正在等待一个
recv()
,它们是否仍然有可能混淆彼此的返回数据?不,连接对象对于每个客户端进程都是唯一的,就像套接字一样。编程模型有意地与socketsapi非常相似。您需要将cmd的结果写入conn,这样正确的客户端进程才能得到结果。@BugSpray我已经添加了一些关于如何工作的详细信息。啊,好的。因此,为了确认,我可以在所有客户端应用程序中使用相同的
客户端('somefile','AF_UNIX')
(无需为每个客户端使用不同的
地址
参数?(抱歉,API文档不清楚)是的,您必须使用相同的域套接字地址(只是一个名称)在所有客户端进程中。在封面下,它只是一个命名管道。有关详细信息,请参阅。