5

私は最近、ソフトウェアにマルチプロセッシングを組み込むという課題を抱えています。メインプロセスでサブプロセスを生成したいのですが、ログ情報をメインプロセスに送り返す方法が必要です。これは主に、使用するモジュールが警告メッセージとエラーメッセージをログオブジェクトに書き込み、これらのメッセージをメインプロセスで実行されるGUIに表示するためです。

明らかなアプローチは、puts()をキューに入れるwrite()メソッドを使用して小さなクラスを作成し、このクラスをロギングストリームハンドラーで使用することでした。次に、メインプロセスはこのキューからget()を実行して、テキストをGUIに送信します。しかし、これはうまくいかなかったようで、理由はわかりません

問題を実証するために、いくつかのサンプルコードを作成しました。ロギングオブジェクトを使用してサブプロセスにキューを書き込み、メインプロセスがキューからの読み取りを試みますが失敗します。誰かが私がこれの何が悪いのかを理解するのを手伝ってもらえますか?

import time, multiprocessing, queue, logging

class FileLikeQueue:
    """A file-like object that writes to a queue"""
    def __init__(self, q):
        self.q = q
    def write(self, t):
        self.q.put(t)
    def flush(self):
        pass


def func(q):
    """This function just writes the time every second for five 
    seconds and then returns. The time is sent to the queue and 
    to a logging object"""

    stream = FileLikeQueue(q)

    log = logging.getLogger()
    infohandler = logging.StreamHandler(stream)
    infohandler.setLevel(logging.INFO)
    infoformatter = logging.Formatter("%(message)s")
    infohandler.setFormatter(infoformatter)
    log.addHandler(infohandler)

    t1 = time.time()
    while time.time() - t1 < 5: #run for five seconds
        log.info('Logging: ' + str(time.time()))
        q.put('Put: %s' % str(time.time()))
        time.sleep(1)



def main():
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=func, args=(q,))
    p.start()

    #read the queue until it is empty
    while True:
        try:
            t = q.get()
        except queue.Empty:
            break
        print(t)


if __name__ == '__main__':
    main()

出力は次のようになると思います。

Logging: 1333629221.01
Put: 1333629221.01
Logging: 1333629222.02
Put: 1333629222.02
Logging: 1333629223.02
Put: 1333629223.02
Logging: 1333629224.02
Put: 1333629224.02
Logging: 1333629225.02
Put: 1333629225.02

しかし、私が得るものは次のとおりです。

Put: 1333629221.01
Put: 1333629222.02
Put: 1333629223.02
Put: 1333629224.02
Put: 1333629225.02

したがって、func()のput()操作は機能しますが、ロギングは機能しません。なんで?

ありがとうございました。

4

1 に答える 1

4

あなたの問題は、ロギングモジュールの設定にあります:

に電話する必要がありますlog.setLevel(logging.INFO)。デフォルトのログ レベルはWARNINGであるため、ログは無効です。

setLevelハンドラー オブジェクトを呼び出しましたが、ログに記録されたメッセージはロガーによってフィルター処理されているため、ハンドラーに到達しません。setLevelデフォルトですべてのメッセージを処理するため、ハンドラー自体を呼び出す必要はありません。

于 2012-04-05T13:13:36.467 に答える