csv.DictWriter 的类型注释

type annotations for csv.DictWriter

我的注释打错了 csv.DictWriter。我正在使用 mypy 0.910 和 python 3.9.9.

def csv_bytes_from_dict_list(dict_list: List[Dict[str, Union[str, int]]]) -> bytes:
    with TextIOWrapper(BytesIO(), encoding="utf-8") as r:
        w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)
        w.writeheader()
        w.writerows(dict_list)
        r.flush()
        r.buffer.seek(0)
        b = r.buffer.read()
    return b

Mypy 显示以下错误。我不确定如何修复它们。

test.py: note: In function "csv_bytes_from_dict_list":
test.py:10:13: error: Need type annotation for "w"  [var-annotated]
            w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)
                ^
test.py:10:38: error: Argument "fieldnames" to "DictWriter" has incompatible type "KeysView[str]"; expected "Sequence[<nothing>]"  [arg-type]
            w = DictWriter(r, fieldnames=dict_list[0].keys(), quotechar='"', quoting=QUOTE_ALL)

当我做的时候

w: DictWriter = ...

我收到以下错误

error: Missing type parameters for generic type "DictWriter"

当我这样做时:

w: DictWriter[Dict[str, Union[str, int]]] = ...

我收到以下错误。

Argument 1 to "writerows" of "DictWriter" has incompatible type "List[Dict[str, Union[str, int]]]"; expected "Iterable[Mapping[Dict[str, Union[str, int]], Any]]" 

至于列表,以下内容无济于事。

fieldnames=list(dict_list[0])

显示

Argument 1 to "list" has incompatible type "Dict[str, Union[str, int]]"; expected "Iterable[Dict[str, Union[str, int]]]"  [arg-type]
                r, fieldnames=list(dict_list[0]), quotechar='"', quoting=QUOTE_ALL

因此,通过尝试 DictWriter 的类型,我注意到无论我在其中插入什么类型,都会显示为写入行方法的第一种类型的预期类型,本质上是映射的键。

例如

# if w is typed like this
w: DictWriter[Dict[str, Union[str, int]]
# the arguments for w.writerows expects this type
Iterable[Mapping[Dict[str, Union[str, int]], Any]]

# if the type for w is
w: DictWriter[dict]
# the expected type for w.writerows is 
Iterable[Mapping[Dict[Any, Any], Any]]

基于此,我得出结论,DictWriter 的类型应该是映射中键的类型。

# only the type of the keys
w: DictWriter[str]
# now the expected type for w.writerows also makes sense
# althogh its showing 'Any' as second type. I am not sure how to impove that
Iterable[Mapping[str, Any]]

结合 list(dict_list[0]) 解决了打字错误。

w: DictWriter[str] = DictWriter(r, fieldnames=list(dict_list[0]), ...)