带和不带“ as”子句的上下文管理器的区别

问题描述 投票:5回答:1

首先,我要道歉,因为我尚无法为我的问题提供清晰的MCVE。我的问题是我在代码库中遇到的一个奇怪现象,我想了解这是如何发生的,所以从某种意义上讲,我想问如何才能针对这种现象create MCVE 。

tl; dr

在根本不使用分配的变量的as语句中是否使用with子句有多重要?

加长版

我们正在使用Airflow(Apache项目),并且存在一个名为DAG的类。此类应用作with子句的上下文管理器,如下所示:

with DAG(**some_parameters) as dag:
    do_something_with(dag)

这按预期工作。

但是,在某些情况下,我们不在dag子句中使用with变量,因此IDE会发出警告,然后将其重命名为_dag(以声明不使用),我尝试删除完全as dag子句:

with DAG(**some_parameters):
    do_something_without_passing_dag()

据我对Python的理解,它应该等效于运行时带有as dag子句的版本:

with DAG(**some_parameters) as dag:
    do_something_without_passing_dag()

但是,令人惊讶的是,在Airflow项目的背景下,两者之间似乎有所不同。使用as dag子句,代码可以按预期工作;如果没有as dag子句,则会显示错误(请参见本文结尾)。令人痛苦的是,此错误出现在Airflow流程的日志中,根本不包含对我的代码的引用。

我需要指出的是,在Airflow上下文中,这些with语句位于小模块的顶层,所以as语句创建模块全局变量(如果存在)。我不知道这是否相关。如果是这样,我不明白为什么。

据我所知,如果我根本不使用变量,则是否提供as子句应该不起作用。不过,这里似乎还是这样。我已经研究了三个方面:

    我监视了__enter__()类的DAG方法的输入和输出。在这两种情况下,输入(参数)和输出(返回值)都相同(返回值当然是上下文管理器对象)。因此,根据as子句的存在,此处似乎没有任何区别。
  1. [使用as子句时,在with子句中,我删除了变量(del dag)作为第一条语句。然后,此版本的行为类似于没有as子句的版本,即。 e。它引发了一个错误。
  2. 我看了source of the DAG,发现它在__enter__() method中将当前上下文对象存储在__enter__()中,并且DagContext class可以(DagContext)从do_something_without_passing_dag()中访问and will对象。 C0]。但是由于所有这些都与使用DAG语句创建的变量无关,所以我看不出这怎么回事。
  3. 任何人都可以解释为什么会这样吗?

这里是我可以在气流日志中找到的错误堆栈跟踪:

DagContext

首先,我要道歉,因为我还不能为我的问题提供清晰的MCVE。我的问题是我在代码库中遇到的一个奇怪现象,我想了解...
python with-statement contextmanager
1个回答
0
投票
您的do_something_without_passing_dag()不应该知道DAG(** some_parameters)应该在其参数“ dag”中传递。
© www.soinside.com 2019 - 2024. All rights reserved.