在Python中并行运行类方法多次

时间:2014-10-16 14:21:10

标签: python sockets multiprocessing socketserver

我已经实现了一个Python套接字服务器。它将来自多个摄像头的图像数据发送到客户端。我的请求处理程序类如下所示:

class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(1024)
            if data.endswith('0000000050'): # client requests data

                for camera_id, camera_path in _video_devices.iteritems():
                    message = self.create_image_transfer_message(camera_id, camera_path)
                    self.request.sendto(message, self.client_address)

     def  create_image_transfer_message(self, camera_id, camera_path):
         # somecode ...

由于客户端,我被迫坚持socket服务器。然而问题是它按顺序工作,因此上传的相机图像之间存在大的延迟。我希望并行创建传输消息,并在调用之间稍有延迟。

我尝试使用pool class中的multiprocessing

import multiprocessing

class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):

    ...

   pool = multiprocessing.Pool(processes=4)
   messages = [pool.apply(self.create_image_transfer_message, args=(camera_id, camera_path)) for camId, camPath in _video_devices.iteritems()]

但是这引发了:

PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

我想知道是否有另一种方法可以在调用之间定义延迟并创建这些传输消息?

编辑:

我使用来自多个摄像头的数据创建响应消息。问题是,如果我运行图像抓取程序太接近彼此,我会得到图像伪像,因为USB总线过载。我想通过,以0.2秒延迟顺序调用图像将解决问题。在图像抓取功能运行的整个过程中,摄像机不会发送数据,因此延迟的并行校准会产生良好的图像,两者之间只有很小的延迟。

2 个答案:

答案 0 :(得分:1)

我认为你已经走上了正确的道路,不需要丢弃你的工作。

以下是我在搜索“how to use a class method with multiprocessing”后通过Google找到的multiprocessing class method的答案

from multiprocessing import Pool
import time

pool = Pool(processes=2)

def unwrap_self_f(arg, **kwarg):
    return C.create_image_transfer_message(*arg, **kwarg)

class RequestHandler(SocketServer.BaseRequestHandler):

    @classmethod
    def create_image_transfer_message(cls, camera_id, camera_path):
        # your logic goes here

    def handle(self):
        while True:
            data = self.request.recv(1024)
            if not data.endswith('0000000050'): # client requests data
                continue

            pool.map(unwrap_self_f, 
                (
                    (camera_id, camera_path)
                    for camera_id, camera_path in _video_devices.iteritems()
                )
            )

注意,如果您想要返回工作人员的值,那么您需要探索using a shared resource,请在此处查看此答案 - How can I recover the return value of a function passed to multiprocessing.Process?

答案 1 :(得分:0)

这段代码对我有用:

class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        while True:
            data = self.request.recv(1024)
            if data.endswith('0000000050'): # client requests data

                process_manager = multiprocessing.Manager()
                messaging_queue = process_manager.Queue()
                jobs = []

                for camId, camPath in _video_devices.iteritems():
                    p = multiprocessing.Process(target=self.create_image_transfer_message,
                                                args=(camera_id, camera_path, messaging_queue))
                    jobs.append(p)
                    p.start()
                    time.sleep(0.3)

                # wait for all processes to finish
                for p in jobs:
                    p.join()

                while not messaging_queue.empty():
                    self.request.sendto(messaging_queue.get(), self.client_address)