Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Python队列与;加上;陈述_Python_Python 2.7 - Fatal编程技术网

将Python队列与;加上;陈述

将Python队列与;加上;陈述,python,python-2.7,Python,Python 2.7,在with语句中使用PythonQueue是否有一种标准方法?这是我希望能够使用它的方式: import Queue myqueue = Queue.Queue() ... ... ... with myqueue as nextItem: doStuff(nextItem) 对于队列对象,没有\uuuu进入或\uu退出方法,因此这不起作用。有没有语法上的糖分让它看起来比这个更好 import Queue myqueue = Queue.Queue() ... ... ... try:

with
语句中使用Python
Queue
是否有一种标准方法?这是我希望能够使用它的方式:

import Queue
myqueue = Queue.Queue()
...
...
...
with myqueue as nextItem:
    doStuff(nextItem)
对于
队列
对象,没有
\uuuu进入
\uu退出
方法,因此这不起作用。有没有语法上的糖分让它看起来比这个更好

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

Edit:在本例中,我有两个原因想使用
with
语句。首先,我认为
with
语句将有助于我的代码更干净一点,特别是当不仅仅是对
doStuff
的单个调用时。第二,如果有一些简单的东西,我可以养成每次都使用的习惯,这样我就不会忘记调用
task\u done
,或者遇到错误可能导致调用被跳过的情况。

答案似乎是否定的-没有内置的方法可以做到这一点

然而,正如斯威尼罗德所提到的,可以对队列进行子类化,并添加
\uuuuuuuu进入
\uuuuuu退出
方法。看起来是这样的:

import Queue

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

    def __exit__(self, excType, excValue, traceback):
        self.task_done()
with myqueue.task() as next_task:
    doStuff(next_task)
这将允许像我上面展示的那样使用它,尽管这有一个问题,即它将队列视为一个任务。为了解决这个问题,我们可以使用创建一个充当上下文管理器的方法

import Queue
from contextlib import contextmanager

class MyQueue(Queue.Queue):
    @contextmanager
    def task(self):
        try:
            yield self.get()
        finally:
            self.task_done()
您将按如下方式使用此版本:

import Queue

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

    def __exit__(self, excType, excValue, traceback):
        self.task_done()
with myqueue.task() as next_task:
    doStuff(next_task)

也可以让
任务
退出
方法进行一些异常处理,尽管这两种方法在处理方式上有一些不同。

有两个简单的选项可以确保无论发生什么情况,都会在队列上调用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()

使用第二种形式需要额外的一行代码,但考虑到可读性,它非常清楚上下文管理器将要做什么

我认为你的一切都很好。花时间担心更大的问题。:)使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?但我真的不认为这有多重要。除非你在玩代码高尔夫(你为什么这么做,要有效率,不要学究气),否则没有理由像这样过度优化。我不认为这是对
with
语句的特别好的使用
将myqueue作为下一个项目
似乎令人困惑,您
myqueue
不是队列中的项目,因此将其
视为
我觉得不合逻辑。我认为使用myqueue.get()作为nextitem有意义。请记住,“上下文管理器”应该在上下文中执行某些操作。队列不是上下文。我认为上下文可能类似于“在任务中”,但如果你真的想为此滥用某些东西,请滥用生成器,而不是上下文管理器。如果其他人感到困惑,
yield
语句本身应该与说
yield None
相同。我们不在乎我们得到了什么,因为我们只真正使用上下文管理器的
\uuuuuuuuuuuuuuuuuuuuuuu
部分。