5

ステートメントで Python を使用する標準的な方法はありQueueますか? withこれは私がそれを使用できるようにしたい方法です:

import Queue
myqueue = Queue.Queue()
...
...
...
with myqueue as nextItem:
    doStuff(nextItem)

__enter__オブジェクトにはor__exit__メソッドがないQueueため、これは機能しません。これよりも見栄えを良くするための構文糖衣はありますか?

import Queue
myqueue = Queue.Queue()
...
...
...
try:
    nextItem = myqueue.get()
    doStuff(nextItem)
finally:
    myqueue.task_done()

編集with:この場合、ステートメントを使用したい理由は2つあります。まず、withステートメントを使用すると、コードが少しきれいになると思います。特にdoStuff. task_done2 つ目は、呼び出しを忘れたり、エラーによって呼び出しがスキップされるような状況が発生しないようにするために、毎回使用する習慣を身につけることができる単純なものがあるとよいでしょう。

4

2 に答える 2

3

task_done() が何があってもキューで呼び出されるようにする簡単なオプションがいくつかあります。これらは、キューからアイテムを処理する必要がある作業が複雑な場合や、各アイテムを処理するためのコード パスが複数ある場合に特に便利です。

最初のオプションは、キューに固有です。Rob が提案したものと似ていますが、Queue のサブクラスを作成する必要はありません。

@contextlib.contextmanager
def mark_done(queue):
    try:
        yield queue.get()
    finally:
        queue.task_done()

queue = Queue()
# assume you put stuff in the queue
with mark_done(queue) as item:
    item.do_stuff()

私は、コード ブロックの最後で関数を呼び出したいときに便利な、より一般的な形式が好きです。その関数は、ブロックの上部にあるオブジェクトに関連しています。

@contextlib.contextmanager
def defer(func):
    try:
        yield
    finally:
        func()

queue = Queue()
# assume you put stuff in the queue
item = queue.get()
with defer(queue.task_done):
    item.do_stuff()

この 2 番目の形式を使用するには、コードを 1 行追加する必要がありますが、読みやすさを考慮すると、コンテキスト マネージャーが何をするのかが非常に明確になります。

于 2016-07-27T22:49:59.260 に答える
2

答えはノーのようです-これを行う組み込みの方法はありません。

ただし、sweenerod が述べたように、Queue および add メソッドをサブクラス化することは可能__enter__です__exit__。それは次のようになります。

import Queue

class MyQueue(Queue.Queue):
    def __enter__(self):
        return self.get()

    def __exit__(self, excType, excValue, traceback):
        self.task_done()

これにより、上で示したように使用できるようになりますが、キューをタスクのように扱うという問題があります。これを修正するには、contextlibを使用して、コンテキスト マネージャーとして機能するメソッドを作成します。

import Queue
from contextlib import contextmanager

class MyQueue(Queue.Queue):
    @contextmanager
    def task(self):
        try:
            yield self.get()
        finally:
            self.task_done()

このバージョンは次のように使用します。

with myqueue.task() as next_task:
    doStuff(next_task)

taskメソッドとメソッドで何らかの例外処理を行うこともできますが、その__exit__方法にはいくつかの違いがあります。

于 2013-10-18T19:01:55.090 に答える