将参数传递给上下文管理器

2024-05-10 21:28:34 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有使用上下文管理器传递参数的方法?以下是我想做的:

async with self.request.app['expiration_lock']('param'):

但我得到了一个错误:

TypeError: 'OrderStatusLock' object is not callable

类OrderStatusLock:

class OrderStatusLock(_ContextManagerMixin, Lock):
    def __init__(self, *args, loop=None):
        print(args)
        self._waiters = None
        self._locked = False
        if loop is None:
            self._loop = events.get_event_loop()
        else:
            self._loop = loop

    async def acquire(self, *args):
        print('acq', args)
        if (not self._locked and (self._waiters is None or
                all(w.cancelled() for w in self._waiters))):
            self._locked = True
            return True

        if self._waiters is None:
            self._waiters = collections.deque()
        fut = self._loop.create_future()
        self._waiters.append(fut)
        try:
            try:
                await fut
            finally:
                self._waiters.remove(fut)
        except CancelledError:
            if not self._locked:
                self._wake_up_first()
            raise

        self._locked = True
        return True

如果可能的话,我可以用这个来面对什么问题?多谢各位


Tags: selfnonelooptrueasyncifisdef
1条回答
网友
1楼 · 发布于 2024-05-10 21:28:34

你的问题有很多,我不知道你的_ContextManagerMixin课来自哪里。我对异步也不太了解

然而,这里有一个简单的(非异步)模式演示,其中一个参数可以传递给上下文管理器,从而改变上下文管理器的__enter__方法的操作方式

记住:上下文管理器的核心只是一个实现__enter__方法和__exit__方法的类。在with块的开头调用__enter__方法,在with块的结尾调用__exit__方法

在我的示例类中添加的__call__方法在__enter__方法之前立即调用,并且与__enter__方法不同,可以使用参数调用。__exit__方法负责清理__call__方法和__enter__方法对类的内部状态所做的更改

from threading import Lock

class LockWrapper:
    def __init__(self):
        self.lock = Lock()
        self.food = ''

    def __enter__(self):
        self.lock.acquire()
        print(f'{self.food} for breakfast, please!')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.lock.release()
        self.food = ''
        return True

    def __call__(self, spam_preferred: bool):
        if spam_preferred:
            self.food = 'Spam'
        else:
            self.food = 'Eggs'
        return self

breakfast_context_manager = LockWrapper()

with breakfast_context_manager(spam_preferred=True):    # prints 'Spam for breakfast, please!'
    pass

with breakfast_context_manager(spam_preferred=False):    # prints 'Eggs for breakfast, please!'
    pass

注意:我上面的示例将抑制在with语句体中引发的所有异常。如果不想抑制任何异常,或者只想抑制某些类型的异常,则需要更改__exit__方法的实现

还要注意,这些函数的返回值非常重要__call__必须返回self,如果您希望类能够调用__enter__^如果希望能够访问with语句体中上下文管理器的内部状态,{}必须返回self^如果希望异常被抑制,{}应该返回True,如果希望遇到的异常在with语句之外继续存在,{}应该返回True

您可以找到一个关于上下文管理器here的好教程。本教程还包含一些关于如何使用__aenter____aexit__方法为异步代码调整上述模式的信息

相关问题 更多 >