如何对csv.writer返回的对象进行类型注释?

问题描述 投票:7回答:3

我想对cv.writer返回的对象进行类型注释。csv.writer 以符合更大的代码库。不幸的是,我无法弄清楚拟合返回类型。

>>> import csv
>>> writer = csv.writer(open('outfile.csv', 'w'))
>>> type(writer)
<class '_csv.writer'>

如果我尝试使用这个类名。

>>> import _csv
>>> writer: _csv.writer = csv.writer(open('outfile.csv', 'w'))

我得到了以下的mypy错误。

Invalid type "_csv.writer"

有人知道在这种情况下应该使用哪种类型吗?当然,我可以使用 typing.Any 但这使类型注释的意义失效。

python mypy
3个回答
1
投票

通常情况下,当事情表现得很奇怪时,这就说明typehed并没有完全映射到运行时。如果你看看_csv 叠加 你会发现该类型被命名为 _writer. 所以你应该把注释改为 _csv._writer.


2
投票

一个解决方案是写一个抽象类来表示类型。这也是如何对一些在 打字 模块。对于 csv.writer() 函数,如下所示。

class _CSVWriter:

    @abstractmethod
    def writerow(self, row: List[str]) -> None:
        pass

    @abstractmethod
    def writerows(self, rows: List[List[str]]) -> None:
        pass

    @abstractproperty
    def dialect(self) -> csv.Dialect:
        pass

现在这个类可以被用于类型注释,用于 writer 对象的类型名。由于返回对象的类型名仍然是 _csv.writer 你仍然会得到一个类型错误。为了避免这种情况,你需要将它转为一个 _CSVWriter 对象。

from typing import cast
writer: _CSVWriter = cast(_CSVWriter, csv.writer(open('test', 'w'))

这个解决方案有点啰嗦,但它能做到这一点。


1
投票

简而言之,就是没有办法直接访问类型。读取 _csv模块的C源 将显示出的类型 readerwriter 不被曝光。即使在 Pypy 其中 _csv 模块是在 Python 中实现的,并没有暴露类型。

因此,如果你需要使用它,你将需要使用一个变通方法,通过实例化一个临时的 writer 实例并获取它的类型。

import csv
# We'll need a temporary file-like object, so use a tempfile
from tempfile import TemporaryFile

with TemporaryFile() as t:
    CSVReader = type(csv.reader(t))
    CSVWriter = type(csv.writer(t))

w: CSVWriter = csv.writer('path/to/data.csv')

如果你想把这个逻辑分开,我建议在一个单独的模块中创建类型。

from csv_types import CSVReader, CSVWriter

另一种解决方案(也涉及到编写自己的类型模块),就是效仿 typing 模块的类型定义中的 iore.

© www.soinside.com 2019 - 2024. All rights reserved.