2017-09-18 8 views
1

私は、pythonでキュー処理が不思議に思える場合があります。私が最初にそれを記述してみましょう:Python:プロセス内のスレッドでキュー処理を行う不思議

  1. メインスレッドは、グローバルオブジェクトがスレッドで開始されたメソッドを持っていることを
  2. (オブジェクトが内部のキューを持っている)のメッセージを収集し、処理するための責任があるグローバルオブジェクトを作成します。 (オブジェクトに属する)キューにアクセスし、そこからメッセージを読み取ります。
  3. メインスレッドは、メッセージをグローバルオブジェクトにパブリッシュする一連のプロセスを開始します(マルチプロセス。プロセスあり)。

問題:キュープロセッサのキューは常に空です。私はいくつかのコードに問題があることを示してみましょう:スクリプトの

import threading as t 
import time 
import sys 
from multiprocessing import Process 
if sys.version_info.major is 2: 
    import Queue as queue 
else: 
    import queue 

class ExampleRecorder: 
    queue = queue.Queue() 

    def run(self): 
     self.thread = t.Thread(target=self.start_processor) 
     self.thread.daemon = True 
     self.thread.start() 

    def start_processor(self): 
     while 1: 
      print("PROCESSOR! QUEUE ID: {}. QUEUE SIZE: {}. IS EMPTY: {}".format(id(self.queue), self.queue.qsize(), self.queue.empty())) 
      time.sleep(1) 

    def push_message(self, span): 
     self.queue.put(span) 
     print("RECORDER! QUEUE ID: {}. QUEUE SIZE: {}".format(id(self.queue), self.queue.qsize())) 

er = ExampleRecorder() 
er.run() 

def producer(): 
    while 1: 
     print("Adding an item") 
     er.push_message("foo") 
     time.sleep(1) 


proc = Process(target=producer) 
proc.start() 

出力例は次のようになります。

$ python3 model.py 
PROCESSOR! QUEUE ID: <queue.Queue object at 0x1095f9b70>. QUEUE SIZE: 0. IS EMPTY: True 
Adding an item 
RECORDER! QUEUE ID: <queue.Queue object at 0x1095f9b70>. QUEUE SIZE: 1 
PROCESSOR! QUEUE ID: <queue.Queue object at 0x1095f9b70>. QUEUE SIZE: 0. IS EMPTY: True 
Adding an item 
RECORDER! QUEUE ID: <queue.Queue object at 0x1095f9b70>. QUEUE SIZE: 2 
PROCESSOR! QUEUE ID: <queue.Queue object at 0x1095f9b70>. QUEUE SIZE: 0. IS EMPTY: True 

あなたが見ることができるように、キューがオブジェクトを受信し、成長するが、プロセッサのために、それは常に空です。おそらくそこで何が間違っているのでしょうか? thread-in-a-processで共有キューを処理するのに手間がかかりますか?

P.S. Python 2.7.12と3.5.2でチェックしました

答えて

2

Queue.Queueは同じプロセスでしか動作しません。別のプロセスではなくスレッドで使用されます。

プロセス間通信を行うにはmultiprocessing.Queueインスタンスが必要ですが、キューのインスタンスを明示的にproducerに渡すようにコードを再構成する必要があります。今のように、新しいプロデューサでExampleRecorder定義が評価されると、各プロデューサは異なるインスタンスを作成します。

注:あなたが書いたコードですべてExampleRecorderのインスタンス(同じプロセスで)が同じキューを共有!これがあなたが望むものだと確信していますか? class ...ブロック内queueを定義することにより

queueクラス、NOTそのインスタンスの属性である。これはqueue__init__()に定義することとはまったく異なります。単純な例で:(2つの変数が同じオブジェクトの別名であるかどうかisオペレータテスト)など、詳細について

inst1.queue is inst2.queue 
Out[8]: True 

inst3.queue is inst4.queue 
Out[9]: False 
+1

ありがとう:私たちはqueue属性をテストする場合

from queue import Queue class SampleClass: queue = Queue() class AnotherSample: def __init__(self): self.queue = Queue() inst1 = SampleClass() inst2 = SampleClass() inst3 = AnotherSample() inst4 = AnotherSample() 

、我々は違いを見ます説明! – elgris