Add converter and formatter parameters to csv.reader and csv.writer
还没有人认领这个 Issue。
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 35.9k
- PR 合并指标
- PR 指标待抓取
描述
Feature or enhancement
Proposal:
The conversion between Python values and CSV fields is hard-coded in both directions. The reader converts unquoted fields with float(), and only in the QUOTE_NONNUMERIC and QUOTE_STRINGS modes. The writer converts every non-string value with str().
This is the common cause of several open issues:
- gh-74232 --
boolis written unquoted asTrue, which cannot be read back. - gh-98485 -- the same for
complex;FractionandIntEnumare affected too, andDecimalsilently round-trips throughfloat. - gh-110852 -- there is no way to write floats with a fixed precision, because preformatted strings are quoted in the
QUOTE_NONNUMERICmode. - gh-85002 -- there is no way to reject values which are neither strings nor numbers.
I propose two parameters, mirroring parse_float in json:
csv.reader(f, converter=None)-- called asconverter(index, field)instead offloat().csv.writer(f, formatter=None)-- called asformatter(index, value)instead ofstr(). It must return a string.
index is the 0-based position of the field in the record. Both default to None, which keeps the current behavior. The hooks only replace the existing calls -- what is not passed to float() or str() now is not passed to them either. Quoting is still decided by the original value.
The index goes first, like in enumerate(). This also makes a wrong one-argument callable fail at once: converter=int raises TypeError on the first field instead of taking the index as the base.
The index makes the hooks per-column, which is what the dtype and converters parameters of pandas.read_csv() are used for:
>>> types = [str, int, Decimal, Fraction]
>>> list(csv.reader(['spam,42,1.10,1/2'], quoting=csv.QUOTE_NONNUMERIC,
... converter=lambda i, field: types[i](field)))
[['spam', 42, Decimal('1.10'), Fraction(1, 2)]]
>>> def money(index, value):
... return format(value, '.2f') if index == 2 else str(value)
>>> csv.writer(sys.stdout, formatter=money).writerow(['a', 1, 0.0, 3.14159])
a,1,0.00,3.14159
gh-85002 no longer needs a parameter of its own -- a strict writer is a formatter which refuses everything except numbers.
I have a working prototype (about 90 lines in Modules/_csv.c).
Open question: should these be parameters of the reader and the writer, or attributes of the dialect? A dialect is a portable description of the file syntax -- it is registered under a global name, sniffed, and copied -- so keeping callables out of it seems better.
Linked PRs
- gh-155099
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 Modules/_csv.c 以及提案中描述的 reader/writer 入口点开始;检查现有的 float() 和 str() 转换路径,以及其中提到的原型。比较参数和方言的替代方案,然后使用链接的 gh-155099 工作来确定已达成一致的 API 和完成标准。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- data
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 25/100