簡體   English   中英

Python multiprocessing.Queue修改對象

[英]Python multiprocessing.Queue modifies objects

我有一個應用程序,它實現了像Python中的責任鏈。 有一個進程通過multiprocessing.Queue()將對象傳遞給其他進程,然后其他進程對對象執行操作。 對於被跟蹤的對象的最后修改時間也很重要,因此只有在修改對象時才能執行操作。

我遇到的問題是,從隊列中提取后,對象中的_modified屬性似乎會隨機變化。 但是,_mtime屬性始終是正確的。 下面的示例將運行並(有意)隨機修改DummyObject,然后將其放在每個處理程序進程的Queue上。 然后,每個處理程序將打印它們在對象中收到的_modified和_mtime值。 我希望_modified值在command_func和handler函數中都是相同的,但通常情況並非如此。 如果我從DummyObject中刪除Object_w_mtime繼承,那么我看不到發送和接收對象的任何差異。

我對python比較陌生。 據我所知,應該發生的事情是每次將一個對象放在一個隊列上,它被腌制,然后通過一個管道發送到接收進程,該進程將對象取消。 那是對的嗎? 當對象被pickle / unpickled時,有沒有任何方法可以搞砸對象繼承?

我在Ubuntu 11.10上用Python 2.7.2和2.6.7以及Ubuntu 11.04上的python 2.7.1測試了這個。 有時你必須讓它運行一分鍾左右才能看到行為,因為它似乎是隨機的。

在這里抓住稻草,提前謝謝。

import multiprocessing
import time
import traceback
import os
import random

class Object_w_mtime(object):
    '''
    Parent object that tracks the last time an attribute was modified
    '''
    def __setattr__(self,a_name,a_value):
        if ((a_name not in ('_mtime','_modified')) and
            (a_value != getattr(self,a_name,None))
        ):
            object.__setattr__(self, '_modified', True)
            object.__setattr__(self, '_mtime', time.time())
        object.__setattr__(self, a_name, a_value)
        return True
    #END def

    def reset(self):
        self._modified = False
#END class

class DummyObject(Object_w_mtime):
    def __init__(self):
        self.value = 10

def handler(in_queue = None, handler_id = None):
    print 'PID:' + str(os.getpid()) + ':handler{0}:<RUN>'.format(handler_id)
    while True:
        try:
            obj = in_queue.get(True,61)
            print 'handler{} - _modified'.format(handler_id), obj._modified, ' \t_mtime', obj._mtime
        except multiprocessing.queues.Empty:
            break
        except KeyboardInterrupt:
            break
        except Exception as e:
            print traceback.format_exc()
            break
    return True
#END def

def command_func(next_links = None):
    print 'PID:' + str(os.getpid()) + ':command_func:<RUN>'
    obj = DummyObject()
    while True:
        try:
            # randomly assign a different value to test with a modified and unmodified object
            obj.value = random.randint(0,1)
            print '**************** obj.value = {0} ***************'.format(obj.value)
            print 'command_ - _modified', obj._modified, ' \t_mtime', obj._mtime
            for each in next_links:
                each.put(obj,False)
        except multiprocessing.queues.Empty:
            break
        except KeyboardInterrupt:
            break
        except Exception as e:
            print e
            print traceback.format_exc()
            break
        obj.reset()
        time.sleep(3)
    return True
#END def


if __name__ == '__main__':
    handler_queues = list()
    handler_processes = list()
    # Create a queue and process object for each command handler
    for handler_id in range(1,4):
        queue = multiprocessing.Queue()
        process = multiprocessing.Process(target=handler, args=(queue, handler_id))
        handler_queues.append(queue)
        handler_processes.append(process)

    try:
        # spawn handler processes
        for process in handler_processes:
            process.start()
        # Start sending commands to handlers
        command_func(handler_queues)

    # exit on keyboard interrupt
    except KeyboardInterrupt:
        for process in handler_processes:
            process.join()
    except Exception:
        traceback.print_exc()

簡而言之,您將obj放入隊列后進行修改。

查看http://svn.python.org/view/python/trunk/Lib/multiprocessing/queues.py?revision=76434&view=markup第285行,put()僅將對象放在內部隊列中,如果還沒有運行,啟動后台線程來處理該隊列中的對象。 因此,代碼中的each.put(obj,False)obj.reset()之間存在each.put(obj,False)

您應該只使用具有不可變(副本)對象的隊列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM