在使用上下文管理器时,如何两次使用yield?

4

我想通过上下文管理器隐藏一些 try/except 的复杂性。这里有一个简单的例子:

from contextlib import contextmanager
import mpd

mpdclient = mpd.MPDClient()
mpdclient.connect("localhost", 6600)

@contextmanager
def mpdcontext():
  try:
    yield
  except mpd.ConnectionError:
    mpdclient.connect("localhost", 6600)

with mpdcontext():
  mpdclient.status()

with mpdcontext():
  mpdclient.lsinfo()

现在,据我所知,在调用yield时会执行with语句中的块。在我的情况下,如果出现异常,我会重新连接到mpd。我是否可以在重新连接后再次执行with块?
谢谢。
1个回答

9

简短回答是你不能从上下文管理器中两次获取收益。你可以考虑使用一个装饰器,包装你尝试执行的内容,并在放弃前重试和重新连接一组次数。这里有一个微不足道的(非生产使用)例子,仅仅是为了说明:

import mpd
import functools

HOST = "localhost"
PORT = 6600
mpdclient = mpd.MPDClient()
mpdclient.connect(HOST, PORT)

def withreconnect(retries=1):
    def _wrapper(func):
        @functools.wraps(func)
        def wrapped(*args, **kwargs):
            for _ in range(retries + 1): # Loop retries + first attempt
                try:
                    return func(*args, **kwargs)
                except mpd.ConnectionError:
                    mpdclient.connect(HOST, PORT)
        return _wrapped
    return wrapped

@withreconnect() # Reconnect 1 time, default
def status():
    mpdclient.status()

@withreconnect(retries=3) # Reconnect 3 times
def lsinfo():
    mpdclient.lsinfo()

编辑:在无参数情况下添加了装饰器调用


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接