7

Pythonのcsvライターを使用して、固定幅、スペース区切り、最小限の引用符で囲まれたCSVファイルを書きたいと思います。出力の例:

item1           item2  
"next item1"    "next item2"
anotheritem1    anotheritem2  

私が使用する場合

writer.writerow( ("{0:15s}".format(item1), "{0:15s}".format(item2)) )
...

次に、スペース区切り文字を使用すると、アイテムの書式設定の末尾のスペースが原因で、引用符またはエスケープ ( csv.QUOTE_* 定数に応じて) が追加されるため、書式設定が壊れます。

"item1          " "item2          "
"next item1     " "next item2     "
"anotheritem1   " "anotheritem2   "

もちろん、すべてを自分でフォーマットできます。

writer.writerow( ("{0:15s}{1:15s}".format(item1, item2)) )

しかし、csv ライターを使用する意味はあまりありません。また、アイテムにスペースが埋め込まれていて、引用/エスケープを使用する必要がある場合は、手動で整理する必要があります。言い換えれば、「QUOTE_MINIMAL」として機能するが、末尾のスペースも無視する(存在しない)「QUOTE_ABSOLUTELYMINIMAL」csv定数が必要なようです。

「QUOTE_ABSOLUTELYMINIMAL」の動作を実現する方法、または Python の CSV モジュールを使用して固定幅のスペース区切りの CSV 出力を取得する別の方法はありますか?

CSV ファイルに固定幅機能が必要な理由は、読みやすさです。そのため、読み取りと書き込みの両方で CSV として処理されますが、列構造により読みやすくなります。csv skipinitialspace オプションが余分なスペースを無視するため、読み取りは問題ありません。驚いたことに、書き込みが問題のようです...

編集:現在のcsvプラグインでは達成できないと結論付けています。これは組み込みオプションではなく、Python の csv ライターで区切り記号を引用またはエスケープせずに追加の区切り記号を記述する方法がないように思われるため、手動で実現する合理的な方法がわかりません。したがって、おそらく独自の csv ライターを作成する必要があります。

4

3 に答える 3

8

あなたが直面している基本的な問題は、csv と固定形式が基本的にデータ ストレージの反対のビューであるということです。それらを一緒に機能させることは、一般的な方法ではありません。また、スペースを含むアイテムにのみ引用符がある場合、それらの行の配置が失われます。

testing     "rather hmm "
strange     "ways to    "
"store some " "csv data   "
testing     testing    

そのデータを読み戻すと、同様に間違った結果になります。

'testing' 'rather hmm '
'strange' 'ways to    '
'store some ' 'csv data   '
'testing' 'testing' ''

最後の行の末尾に余分なフィールドがあることに注意してください。これらの問題を考えると、私はあなたの例に行きます

"item1          " "item2          "
"next item1     " "next item2     "
"anotheritem1   " "anotheritem2   "

これは非常に読みやすく、既存のcsvライブラリで簡単に生成でき、読み返すと正しく解析されます。生成に使用したコードは次のとおりです。

import csv

class SpaceCsv(csv.Dialect):
    "csv format for exporting tables"
    delimiter = None
    doublequote = True
    escapechar = None
    lineterminator = '\n'
    quotechar = '"'
    skipinitialspace = True
    quoting = csv.QUOTE_MINIMAL
csv.register_dialect('space', SpaceCsv)

data = (
        ('testing    ', 'rather hmm '),
        ('strange    ', 'ways to    '),
        ('store some ', 'csv data   '),
        ('testing    ', 'testing    '),

temp = open(r'c:\tmp\fixed.csv', 'w')
writer = csv.writer(temp, dialect='space')
for row in data:
    writer.writerow(row)
temp.close()

もちろん、これらすべてを実行する関数に到達する前に、または関数自体で、すべてのデータを同じ長さにパディングする必要があります。ああ、数値データがある場合は、それについてもパディングを考慮する必要があります。

于 2011-08-04T23:51:31.493 に答える
2

これはあなたにとって何をしますか?csv.QUOTE_NONE 定数だけが欠けていたと思います。

import csv
csv.register_dialect('spacedelimitedfixedwidth', delimiter=' ', quoting=csv.QUOTE_NONE)
with open('crappymainframe.out', 'rb') as f:
    reader = csv.reader(f, 'spacedelimitedfixedwidth')

これは、csv モジュール ドキュメントの下部にある unixpwd 方言の例を変更したものです。

于 2011-04-12T20:41:05.530 に答える
0

This active state recipe shows how to output table-ized data in python: http://code.activestate.com/recipes/267662-table-indentation/

You might be able to glean enough from that example to do what you want.

于 2011-04-12T16:23:54.203 に答える