如何在PyCharm中正确注释ContextManager?

Ale*_*eph 2 typing contextmanager pycharm

我如何注释contextmanagerPyCharm 中a的yield类型,以便它正确猜测with子句中使用的值的类型-就像它猜测fcreated in with open(...) as f是文件一样?

例如,我有一个这样的上下文管理器:

@contextlib.contextmanager
def temp_borders_file(geometry: GEOSGeometry, name='borders.json'):
    with TemporaryDirectory() as temp_dir:
        borders_file = Path(dir) / name
        with borders_file.open('w+') as f:
            f.write(geometry.json)
        yield borders_file

with temp_borders_file(my_geom) as borders_f:
    do_some_code_with(borders_f...)
Run Code Online (Sandbox Code Playgroud)

如何让PyCharm知道每个这样borders_f创建的对象都是的pathlib.Path(从而启用上的Path方法的自动完成功能border_f)?当然,我可以像# type: Path在每条with语句之后一样发表评论,但是似乎可以通过适当地注释来完成temp_border_file

我试过Pathtyping.Iterator[Path]typing.Generator[Path, None, None]作为返回类型的temp_border_file,以及增加# type: Pathborders_file上下文管理的代码中,但似乎它并不能帮助。

Pav*_*eev 5

我相信您可以使用ContextManagerfrom typing,例如:

import contextlib
from typing import ContextManager
from pathlib import Path


@contextlib.contextmanager
def temp_borders_file() -> ContextManager[Path]:
    pass


with temp_borders_file() as borders_f:
    borders_f  # has type Path here
Run Code Online (Sandbox Code Playgroud)

  • 自版本 3.9 起,`typing.ContextManager` 已被弃用。我应该仍然使用它还是在同一个地方使用`contextlib.AbstractContextManager`? (2认同)
  • 嗯,确实如此。它应该在 [PY-36444](https://youtrack.jetbrains.com/issue/PY-36444) 中修复在 PyCharm 端。 (2认同)

Tho*_*mas 5

这是当前的 PyCharm 问题:PY-36444

该问题的解决方法是重写以下示例代码:

from contextlib import contextmanager

@contextmanager
def generator_function():
    yield "some value"

with generator_function() as value:
    print(value.upper())  # no PyCharm autocompletion
Run Code Online (Sandbox Code Playgroud)

from contextlib import contextmanager
from typing import ContextManager

def wrapper() -> ContextManager[str]:
    @contextmanager
    def generator_function():
        yield "some value"

    return generator_function()

with wrapper() as value:
    print(value.upper())  # PyCharm autocompletion works
Run Code Online (Sandbox Code Playgroud)

还有一个更简单的方法来注释返回类型,ContextManager[str]但有多种原因:

  • mypy 将正确发出此注释的错误,如 PyCharm 问题中更详细的描述。
  • 这不能保证在未来工作,因为 PyCharm 希望能解决这个问题,因此打破这个解决方法