Как получить доступ к `with`-контексту из других областей в Python? - PullRequest
1 голос
/ 15 января 2020

У меня есть 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 не предлагает (прямой) способ доступа к with -контексту.

Обход, который я нашел так far должен был передать объект progress_bar в качестве необязательного параметра process() и использовать его, если он доступен. Тем не менее, кажется, что излишне менять функцию только для этой цели.

Предоставляет ли Python в целом или tqdm в частности шаблон для обработки этого?

Обновление для фона :

Вариант использования здесь заключается в том, что в реальном коде здесь у меня есть конкатенация вызовов функций. process() на самом деле более сложный и вызывает различные другие функции. Они могут регистрировать вывод, который должен go до progress_bar.write(), если доступно.

Если конечная функция в стеке вызовов не может получить доступ к with -контексту из функции root, мне нужно передать progress_bar объект вниз через все уровни в дереве вызовов.

1 Ответ

1 голос
/ 17 января 2020

Подводя итог комментариям:

  • Нет способа неявного доступа к with -контексту в другой функции (и не должно быть).

  • Лучшее и самое чистое решение - явно передать объект для записи. Для данного варианта использования вы можете / должны использовать значение по умолчанию, например:

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()
...