2017-08-24 4 views
2

csv.DictReaderを使用してTSVファイルを読み込もうとしていますが、読者が間違ったフィールド数を報告しています。私は内部を見たとき、私はそれが分割区切り文字が適切でないことがわかった(私はstr.split(delimiter)awk -F 'delim'で確認python3のcsv.DictReaderが区切り文字でレコードを分割していません。


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に掲載されています。

+1

あなたのCSVコンテンツの例を教えてもらえますか? – asongtoruin

+0

13個の列があるので、12個のキーしか用意されていないので、他の値をグループ化するために余分な 'None'キーを追加してください。それは意図的なのでしょうか? –

+0

@ Jean-FrançoisFabre[docs](https://docs.python.org/3/library/csv.html#csv.reader)によれば、他のキーは無視したいだけです。 –

答えて

1

rawとcsvの構文解析の違い(これが私が入力データ)は、デフォルトではと表示され、と表示されます。

あなたのデータには引用符があり、csvは引用符で保護されたフィールドを1つのフィールドとして扱います。 awkおよびstr.splitは気にしません。

だけ引用考慮しないcsvモジュールを教えて:

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

がこれをやって、私は満たされたすべてのフィールドを取得します。

関連する問題