上下文管理器定义错误

Error with context manager definition

我有以下 Python 脚本:

from contextlib import contextmanager

@contextmanager
def my_content_manager():
    self.entrance = True

    try:
        yield
    except Exception as ex:
        self.entrance = False

with my_content_manager() as cm:
    print (cm.entrance)

print (cm.entrance)

当我尝试 运行 脚本时,我得到以下信息:

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    with my_content_manager() as cm:
  File "C:\Users\abc\AppData\Local\Programs\Python\Python36\lib\contextlib.py", line 82, in __enter__
    return next(self.gen)
  File "test.py", line 5, in my_content_manager
    self.entrance = True
NameError: name 'self' is not defined

这是为什么?我该如何解决这个错误?

谢谢。

错误 NameError: name 'self' is not defined 是不言自明的,没有双关语的意思。 self 只是 classes 方法中约定使用的名称。您没有在任何地方定义 self,所以 Python 不知道该怎么做。此外,您已经定义了一个函数,而不是 class 中的方法,因此这离工作还很远。使用 class 来定义上下文管理器,如下所示:

class MyContextManager(object):
    def __init__(self):
        self.entrance = True

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_val:
            self.entrance = False
        # signal that the exception was handled and the program should continue
        return True


with MyContextManager() as cm:
    print (cm.entrance)
    raise Exception()

print (cm.entrance)

编辑:如果按照评论中的要求,您只想打印一个值而不是将其存储在某处:

@contextmanager
def my_content_manager():
    try:
        yield
    except Exception as ex:
        print(False)
    else:
        print(True)

一般来说,使用 class 可能是更好的方法(正如其他答案所暗示的那样)。但是,我记得函数对象可以有属性。我遇到了 this 相关问题,这导致了以下技巧(这看起来确实是对该功能的滥用):

from contextlib import contextmanager

@contextmanager
def my_content_manager():
    my_content_manager.entrance = True
    try:
        yield my_content_manager.entrance
    finally:
        my_content_manager.entrance = False
my_content_manager.entrance = False

with my_content_manager() as cm:
    print(my_content_manager.entrance)
    # Or, print(cm)

print(my_content_manager.entrance)

此技术可能存在缺陷。我只是出于好奇而发布它。