简体   繁体   English

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

[英]Runing class method multiple times parallel in Python

I have implemented a Python socket server. 我已经实现了一个Python套接字服务器。 It sends image data from multiple cameras to a client. 它将来自多个摄像机的图像数据发送到客户端。 My request handler class looks like: 我的请求处理程序类如下所示:

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 ...

I am forced to stick to the socket server because of the client. 由于客户端原因,我不得不坚持使用套接字服务器。 It works however the problem is that it works sequentially, so there are large delays between the camera images being uploaded. 它可以工作,但是问题在于它可以顺序工作,因此上传的相机图像之间会有很大的延迟。 I would like to create the transfer messages in parallel with a small delay between the calls. 我想并行创建转移消息,并且两次调用之间的延迟很小。

I tried to use the pool class from multiprocessing : 我试图使用multiprocessing中pool类

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()]

But this throws: 但这引发了:

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

I want to know if there is an another way to create those transfer messages in parallel with a defined delay between the calls? 我想知道是否还有另一种方法可以在调用之间定义延迟的同时并行创建这些传输消息?

EDIT: 编辑:

I create the response messages using data from multiple cameras. 我使用来自多个摄像机的数据创建响应消息。 The problem is, that if I run the image grabbing routines too close to each other I get image artifacts, because the USB bus is overloaded. 问题是,如果我的图像获取例程运行得太近,我会得到图像伪影,因为USB总线过载。 I figured out, that calling the image grabbing sequentially with 0.2 sec delay will solve the problem. 我发现,以0.2秒的延迟顺序调用图像捕获将解决此问题。 The cameras are not sending data the whole time the image grabbing function is running, so the delayed parallel cal result in good images with only a small delay between them. 摄像机在整个图像捕获功能运行期间都不会发送数据,因此延迟的并行校准会产生良好的图像,而它们之间只有很小的延迟。

I think you're on the right path already, no need to throw away your work. 我认为您已经走上了正确的道路,无需放弃您的工作。

Here's an answer to how to use a class method with multiprocessing I found via Google after searching for " multiprocessing class method " 这是在搜索“ multiprocessing class method ”后通过Google找到的如何将class方法与multiprocessing一起使用的答案

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()
                )
            )

Note, if you want to return values from the workers then you'll need to explore using a shared resource see this answer here - How can I recover the return value of a function passed to multiprocessing.Process? 注意,如果要从工作程序返回值,则需要使用共享资源进行探索,请参见此处的答案- 如何恢复传递给multiprocessing.Process的函数的返回值?

This code did the trick for me: 这段代码对我有用:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM