sys.stdout和文件的正确输入方式

3

我正在尝试创建一个方法,它可以处理表示文件名的字符串、Path对象或已经打开的输出流(sys.stdout, open('...', 'w'))。我正在努力为mypy设置正确的类型以进行检查。

到目前为止,我已经得到了:

import io
from pathlib import Path
from typing import Union, TextIO, Text


def generate(output: Union[Text, Path, TextIO]) -> None:
    if isinstance(output, io.IOBase):
        output.write("data")
    else:
        if isinstance(output, Text):
            output = Path(output)
        with output.open("w") as output_file:
            output_file.write("data")

但是mypy一直在抱怨:

Item "TextIO" of "Union[Path, TextIO]" has no attribute "open"

据我所知,TextIO是用于文本文件的正确类型,但是无法对这种类型进行isinstance检查。 代码结构确保在出现错误时,我们不可能拥有TestIO对象,因为它已经在之前的分支中被处理过了。
这里应该如何标记所有类型?
1个回答

4

为了将open与路径分支隔离开来,可以重写此代码,因为Mypy理解isinstance检查,并在一个地方调用write

import io
from pathlib import Path
from typing import Union, TextIO, Text
from contextlib import ExitStack


def generate(output: Union[Text, Path, TextIO]) -> None:
    with ExitStack() as stack:
        if isinstance(output, Text):
            output = Path(output)
        if isinstance(output, Path):
            output = stack.enter_context(output.open("w"))
        output.write("data")

1
哦!好清晰明了啊!是的,有两个等号写法不太好看,它有一些代码味道。但我不知道 ExitStack 类,我不能以相同的方式处理所有输入(文本和路径必须打开和关闭,而 TextIO 必须保持原样)。您的建议非常有效,感谢您分享这些知识! - Poshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接