11

如何contextmanager在 PyCharm 中注释 a 的 yield 类型,以便它正确猜测with子句中使用的值的类型 - 就像它猜测fcreated inwith 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...)

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

我尝试了Path,typing.Iterator[Path]typing.Generator[Path, None, None]作为 , 的返回类型temp_border_file,以及在上下文管理器的代码中添加# type: Pathborders_file但似乎没有帮助。

4

2 回答 2

16

我相信您可以使用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
于 2018-03-17T12:04:33.383 回答
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

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

还有一种更简单的解决方法是使用注释返回类型,ContextManager[str]但有多种原因:

  • mypy 将为此注释正确发出错误,如 PyCharm 问题中更详细的描述。
  • 这不保证将来会起作用,因为 PyCharm 有望解决此问题并因此打破此解决方法
于 2019-06-15T14:52:29.437 回答