【问题标题】:python3's csv.DictReader is not splitting records by delimiter as expectedpython3 的 csv.DictReader 没有按预期按分隔符拆分记录
【发布时间】:2017-08-25 02:56:20
【问题描述】:

我正在尝试使用 csv.DictReader 读取 TSV 文件,但是,阅读器报告的字段数错误。当我往里看时,我发现它没有正确分割分隔符(我用str.split(delimiter)awk -F 'delim'确认。


from pprint import pprint
import csv
import sys, os
keys = ['id', 'src', 'src_len', 'sys1_o', 'sys1_b', 'sys1_l',
        'sys2_o', 'sys2_b', 'sys2_l', 'sys3_o', 'sys3_b', 'sys3_l', 'x']
# get this data from https://gist.github.com/thammegowda/95613b203a442fbe72fc5b51af491367 
my_data = """segment-22 Kture . 27  Thutaalchisu.   -   33  Koture. -   27  Th jump.    -   33  3
segment-23  ‘Yunker .   7   "said.  -   8   ‘Yunker.    -   7   "said.  -   8   1"""

tmp_file = "tmp.tsv"
with open(tmp_file, 'w', encoding='utf-8') as f:
    f.write(my_data)

def read_recs_csv(path):
    with open(path, 'rt', encoding='utf-8') as f:
        rdr = csv.DictReader(f, fieldnames=keys, delimiter='\t')
        for rec in rdr:
            yield(dict(rec))

def read_recs_raw(path):
    with open(path, 'rt', encoding='utf-8') as f:
        for line in f:
            rec = dict(zip(keys, line.strip().split('\t')))
            yield(rec)

print("Reading through CSV DictReader ")
pprint(list(read_recs_csv(tmp_file)))
print("Reading directly")
pprint(list(read_recs_raw(tmp_file)))
# Debug
print(sys.version_info)
print(os.environ['LANG'])

输出:

    Reading through CSV DictReader 
[{'id': 'segment-22',
  'src': 'Kture .',
  'src_len': '27',
  'sys1_b': '-',
  'sys1_l': '33',
  'sys1_o': 'Thutaalchisu.',
  'sys2_b': '-',
  'sys2_l': '27',
  'sys2_o': 'Koture.',
  'sys3_b': '-',
  'sys3_l': '33',
  'sys3_o': 'Th jump.',
  'x': '3'},
 {'id': 'segment-23',
  'src': '‘Yunker .',
  'src_len': '7',
  'sys1_b': '-',
  'sys1_l': '8',
  'sys1_o': 'said.\t-\t8\t‘Yunker.\t-\t7\tsaid.',
  'sys2_b': None,
  'sys2_l': None,
  'sys2_o': '1',
  'sys3_b': None,
  'sys3_l': None,
  'sys3_o': None,
  'x': None}]
Reading directly
[{'id': 'segment-22',
  'src': 'Kture .',
  'src_len': '27',
  'sys1_b': '-',
  'sys1_l': '33',
  'sys1_o': 'Thutaalchisu.',
  'sys2_b': '-',
  'sys2_l': '27',
  'sys2_o': 'Koture.',
  'sys3_b': '-',
  'sys3_l': '33',
  'sys3_o': 'Th jump.',
  'x': '3'},
 {'id': 'segment-23',
  'src': '‘Yunker .',
  'src_len': '7',
  'sys1_b': '-',
  'sys1_l': '8',
  'sys1_o': '"said.',
  'sys2_b': '-',
  'sys2_l': '7',
  'sys2_o': '‘Yunker.',
  'sys3_b': '-',
  'sys3_l': '8',
  'sys3_o': '"said.',
  'x': '1'}]
sys.version_info(major=3, minor=6, micro=1, releaselevel='final', serial=0)
en_US.UTF-8

注意:样本数据发布在a gist。如果标签被空格替换,请在此处下载。

【问题讨论】:

  • 你能提供一个你的 csv 内容的例子吗?
  • 请注意,只提供了 12 个键,因为有 13 列,读者添加一个额外的 None 键来分组其他值。这是故意的吗?
  • @Jean-FrançoisFabre 是的,我只是想忽略其他键
  • 根据the docs,您应该使用newline='' 打开文件。这有什么改变吗?
  • 如果您不发布文件的小示例,将无法回答

标签: python python-3.x csv


【解决方案1】:

raw 和 csv 解析之间的区别(这就是我坚持获取输入数据的原因)是 csv 模块默认处理 quoting

您的数据中有引号,csv 将受引号保护的字段视为单个字段。 awkstr.split 不在乎。

告诉csv 模块不要考虑引用:

rdr = csv.DictReader(f, fieldnames=keys, delimiter='\t', quoting=csv.QUOTE_NONE)

这样做,我填满了所有字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多