Контекстный менеджер, не возвращающий значения

Я хочу написать контекстный менеджер, который выглядит примерно так:

@contexlib.contextmanager
def process_started(process: mylib.Process) -> XXX: # ?
    process.start()

    try:
        yield XXX # ?
    except BaseException as e: 
        raise e # reraise any exception
    finally:
        process.finish()
        

То есть ему не надо возвращать какое-то значение, должен использоваться так:

with process_started(process):
    do_background_stuff()

Что в таком случае надо указывать вместо XXX? Какой возвращаемый тип и значение у yield?


Ответы (3 шт):

Автор решения: Stanislav Volodarskiy

Ничего не возвращайте. В аннотации укажите None. yield поддерживает такой синтаксис (который не отличается от yield None):

import contextlib


@contextlib.contextmanager
def f():
    print('before')
    yield
    print('after')


with f():
    print('within')
$ python yield.py 
before
within
after
→ Ссылка
Автор решения: Wen

yield действительно эквивалентно yield None, однако правильной аннотацией будет typing.Generator[None, None, None] (вместо None допустим его тип, но принято None писать), иначе тот же PyCharm будет подчёркивать ваши вызовы next() и send(). Возможный вариант без подчёркиваний typing.NoReturn, но, судя по комментам https://stackoverflow.com/a/36797437, его не принято использовать в такой ситуации.

→ Ссылка
Автор решения: Cookie

Вместо typing.Generator[None, None, None] с Python 3.9 лучше использовать collections.abc.Generator[None, None, None]

→ Ссылка