了解 python3 嵌套上下文管理器

Understand python3 nested context managers

我有一个 class:

class OuterCtxManager:
  def __enter__(self): 
    print('Outer enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Outer exit')

当我这样做时:

def test_func():
  return OuterCtxManager()

with test_func() as context_manager:
  print('context_manager')

它打印:

Outer enter
context_manager
Outer exit

尽管在函数中对已创建的对象使用了上下文管理器,为什么它仍然打印 Outer enterOuter exit? (而不是像 with OuterCtxManager() as ocm 这样创建对象时直接使用)

接下来是有趣的事情:

当我这样做时:

def test_func():
  first_object = OuterCtxManager()
  second_object = OuterCtxManager()
  return [first_object, second_object]

with test_func() as context_manager:
  print('context_manager')

它提高了:

AttributeError: enter

最后,当我这样做时:

class OuterCtxManager:
  def __init__(self):
    self.inner_ctx = InnerCtxManager()
  def __enter__(self): 
    print('Outer enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Outer exit')

class InnerCtxManager:
  def __init__(self):
    print('inner_created')
  def __enter__(self): 
    print('Inner enter')
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('Inner exit')


def test_func():
  first_object = OuterCtxManager()
  return first_object

with test_func() as context_manager:
  print('context_manager')

它打印:

inner_created
Outer enter
context_manager
Outer exit

我没有收到任何错误。我也没有得到 Inner createdInner enter。为什么?

Sandbox

Why does it print Outer enter and Outer exit at all despite using context manager on already created object in a function?

你定义的with语句说python应该在with语句的内容执行前调用__enter__,然后调用__exit__

对象是否已经初始化并不重要。 with 语句无论如何都会调用 __enter____exit__

It raises AttributeError: enter

当您返回一个元组并且该元组不包含 __enter__ 的定义时,将引发此错误。

I don't get any errors. Neither I get Inner created and Inner enter. Why is that so?

您没有收到任何错误,因为您在 OuterCtxManager 中正确使用了 with 语句,并且没有得到输出 Inner enterInner exit,因为您没有在 InnerCtxManager 类型上使用 with 语句。