如何从 Python 中的其他范围访问 `with`-context?

How to access `with`-context from other scope in Python?

我有一个这样的 with 语句:

from tqdm import tqdm

with tqdm(documents) as progress_bar:
    for document in documents:
        if [...]:
            process(document)
            progress_bar.update()

process() 是另一个函数,我想在其中根据上下文中是否存在 tqdm 实例(从上面的代码调用)或不存在(从某处调用)来调整日志记录别的)。在伪代码中,例如:

def process(document):
     if <tqdm in context>:
       progress_bar.write("processing")
     else:
       logging.info("processing")

我可以从父范围动态查找和访问 with 上下文(在本例中由 tqdm 提供)吗?怎么样?

contextlib documentation 不提供访问 with 上下文的(直接)方式。

到目前为止我找到的解决方法是将 progress_bar 对象作为可选参数传递给 process(),并在可用时使用它。然而,仅仅为了这个目的而改变功能似乎是多余的。

一般来说,Python,或者具体来说,tqdm,是否提供了处理这个问题的模式?

后台更新:

这里的用例是,在此处的真实代码中,我有一系列函数调用。 process() 实际上更复杂并且调用了各种其他函数。这些可能会记录输出,如果可用,应该转到 progress_bar.write()

如果调用堆栈中的叶函数无法从根函数访问 with-context,我需要将 progress_bar 对象向下传递到调用树中的所有级别。

总结评论:

  • 无法在另一个函数中隐式访问 with-context(也不应该)。

  • 最好和最干净的解决方案是显式传递用于写入的对象。对于给定的用例,您 can/should 使用这样的默认值:

def process(document, writer: Callable[[str], Any] = logging.info):
    writer("processing")    
    [...]

为了写入 tqdm 实例而不是记录器,您可以这样调用 process()

from tqdm import tqdm

with tqdm(documents) as progress_bar:
    for document in documents:
        if [...]:
            process(document, writer=progress_bar.write)
            progress_bar.update()