如何对 csv.writer 返回的对象进行类型注释?
How to type-annotate object returned by csv.writer?
我想将类型注释应用于 csv.writer
的 returned 对象,以符合更大的代码库。不幸的是,我无法找出合适的 return 类型。
>>> 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 中实现 _csv 模块的 C source of the _csv module will show that the types of reader
and writer
are not exposed. Even in Pypy,不会公开类型。
因此,如果您需要使用它,则需要通过实例化 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
另一个解决方案(也涉及编写您自己的类型模块)是在 io
和 re
类型定义中遵循 typing
模块的示例.
一个解决方案是写一个代表类型的抽象class。这也是 typing module. For the csv.writer()
函数中某些 classes 的处理方式,如下所示:
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
现在这个 class 可以用在 writer
对象的类型注释中。由于返回对象的类型名称仍然是 _csv.writer
,您仍然会收到类型错误。为避免这种情况,您需要将其转换为 _CSVWriter
对象。
from typing import cast
writer: _CSVWriter = cast(_CSVWriter, csv.writer(open('test', 'w'))
该解决方案有点冗长,但可以完成工作。
通常情况下,当事情表现得很奇怪时,这是一个符号类型没有完全映射到运行时。如果您查看 _csv in typeshed,您会看到该类型被命名为 _writer
。所以你应该可以注释 _csv._writer
.
我 运行 遇到了 typeshed defs 的问题并最终使用了以下内容:
class Writer(Protocol):
def writerow(self, row: Iterable[Any]) -> Any:
...
def writerows(self, rows: Iterable[Iterable[Any]]) -> None:
...
Reader = Iterator[Any]
writer: Writer = csv.writer(open('outfile.csv', 'w'))
reader: Reader = csv.writer(open('outfile.csv', 'w'))
我看到原来的 class 继承自 Iterator
所以我能够做到:
from typing import Iterator
with open(spec_file) as csv_file:
spec_csv: Iterator = csv.reader(csv_file)
然后 mypy
瞧:
Success: no issues found in 1 source file
我想将类型注释应用于 csv.writer
的 returned 对象,以符合更大的代码库。不幸的是,我无法找出合适的 return 类型。
>>> 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 中实现 _csv 模块的 C source of the _csv module will show that the types of reader
and writer
are not exposed. Even in Pypy,不会公开类型。
因此,如果您需要使用它,则需要通过实例化 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
另一个解决方案(也涉及编写您自己的类型模块)是在 io
和 re
类型定义中遵循 typing
模块的示例.
一个解决方案是写一个代表类型的抽象class。这也是 typing module. For the csv.writer()
函数中某些 classes 的处理方式,如下所示:
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
现在这个 class 可以用在 writer
对象的类型注释中。由于返回对象的类型名称仍然是 _csv.writer
,您仍然会收到类型错误。为避免这种情况,您需要将其转换为 _CSVWriter
对象。
from typing import cast
writer: _CSVWriter = cast(_CSVWriter, csv.writer(open('test', 'w'))
该解决方案有点冗长,但可以完成工作。
通常情况下,当事情表现得很奇怪时,这是一个符号类型没有完全映射到运行时。如果您查看 _csv in typeshed,您会看到该类型被命名为 _writer
。所以你应该可以注释 _csv._writer
.
我 运行 遇到了 typeshed defs 的问题并最终使用了以下内容:
class Writer(Protocol):
def writerow(self, row: Iterable[Any]) -> Any:
...
def writerows(self, rows: Iterable[Iterable[Any]]) -> None:
...
Reader = Iterator[Any]
writer: Writer = csv.writer(open('outfile.csv', 'w'))
reader: Reader = csv.writer(open('outfile.csv', 'w'))
我看到原来的 class 继承自 Iterator
所以我能够做到:
from typing import Iterator
with open(spec_file) as csv_file:
spec_csv: Iterator = csv.reader(csv_file)
然后 mypy
瞧:
Success: no issues found in 1 source file