2009-06-09 19 views
9

明らかに、csv出力の実装に​​よっては、フィールドの区切り文字が最後の行の右側から切り捨てられ、フィールドがNULLの場合はファイルの最後の行のみが切り捨てられます。csv.readerに最後の行があることを伝える

例入力CSV、フィールド「C」と「D」はNULL可能です:下記のスクリプトのようなもので

a|b|c|d 
1|2|| 
1|2|3|4 
3|4|| 
2|3 

、どのように私は私が対処する方法を知って、私は最後の行にしていますかどうかを伝えることができますそれは適切ですか?

import csv 

reader = csv.reader(open('somefile.csv'), delimiter='|', quotechar=None) 

header = reader.next() 

for line_num, row in enumerate(reader): 
    assert len(row) == len(header) 
    .... 
+3

投稿した内容はCSVではありません。 CSVは「Comma Sepaerated Values」の略です。セパレータはカンマでなければなりません。 –

+6

ほとんどのcsv実装では、セパレータとして代替文字を指定することができます –

+0

@ Neeil:huh? "CSV(カンマ区切り値)形式は、スプレッドシートとデータベースのための最も一般的なインポートとエクスポートの形式ですが、" CSV標準 "はありません[..]それでも区切り文字と引用文字は異なりますが、 [..] " – SilentGhost

答えて

13

基本的にはあなただけあなたが不足してきた後を実行してきました知っています。たとえば、readerイテレータをラップすることができます。次のように:

def isLast(itr): 
    old = itr.next() 
    for new in itr: 
    yield False, old 
    old = new 
    yield True, old 

とするようにコードを変更します。

for line_num, (is_last, row) in enumerate(isLast(reader)): 
    if not is_last: assert len(row) == len(header) 

など

+1

私はitertools'はこのようなものを持っていないことに驚いています。繰り返し使用するユースケースです。 –

0

ただ、ヘッダの長さに行を拡張:

for line_num, row in enumerate(reader): 
    while len(row) < len(header): 
     row.append('') 
    ... 
0

でしたあなたはありませんcsvリーダーが最後の行を読み取ったときにエラーをキャッチする

try: ...あなたのものはここに... を除く:StopIteration

状態?

試みを使用する方法の例についてstackoverflowの上、次のpythonコードを参照してください:キャッチ:Python CSV DictReader/Writer issues

+0

はあなたが最後の行にいるときにあなたに知らせません。あなたが最後の行を渡した後にのみあなたに伝えます。 –

+1

私はあなたの質問をもう一度読み直しました。あなたが正しいと思うのはあなたが求めているものではありません。最後の行に対処する方法が必要です。なぜ以下のJohn Machinのソリューションを使用できないのですか? –

2

あなたは、各行の列の固定数の期待を持っている場合、あなたはに対して防御的でなければなりません。

(1)ANY行が短い - たとえばライター(SQL Server/Query Analyzer IIRC)は末尾NULLを省略することがありますランダムに;ユーザーは、空白行を残してテキストエディタを使用してファイルを操作することがあります。

(2)ANY行が長くなっています。コンマは正しく引用されていません。

あなたはファンシートリックは必要ありません。ただ、昔ながらの場合、テストあなたの行読んで、ループ内:

for row in csv.reader(...): 
    ncols = len(row) 
    if ncols != expected_cols: 
     appropriate_action() 
+0

私は同意しますが、このデータの送信元が正しくフォーマットされたデータを送信できない/拒否しています。私は自分自身の癖を処理する以外に選択肢はありません。 –

+0

はい、あなたは自分自身の癖を自分で処理しなければなりません。「最後の行の末尾のnullフィールドが見つからない」よりも多くの癖があることを指摘しています。あなたの "but"を理解してください。 –

0

あなたがfor row in reader:を使用する場合は、最後の項目が読み込まれた後、それだけでループを停止します。あなたはまさに最後の行は、このコードを試す取得したい場合

1

:あなたが行の値で作業を続けたい場合は

with open("\\".join([myPath,files]), 'r') as f: 
    print f.readlines()[-1] #or your own manipulations 

を次のようにします。

f.readlines()[-1].split(",")[0] #this would let you get columns by their index 
1

私はそれは承知しています古い質問ですが、私は提示されたものとは異なる答えを考え出しました。readerオブジェクトは、繰り返し処理するときにline_num属性をインクリメントします。次に、最初にrow_countを使用して合計行数を取得してから、それをline_numと比較します。

import csv 

def row_count(filename): 
    with open(filename) as in_file: 
     return sum(1 for _ in in_file) 

in_filename = 'somefile.csv' 
reader = csv.reader(open(in_filename), delimiter='|') 

last_line_number = row_count(in_filename) 
for row in reader: 
    if last_line_number == reader.line_num: 
     print "It is the last line: %s" % row 
関連する問題