在Python中写入固定宽度、以空格分隔的CSV输出
我想用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_ABSOLUTELYMINIMAL"的csv常量,它的作用和"QUOTE_MINIMAL"一样,但会忽略尾部的空格。
有没有办法实现"QUOTE_ABSOLUTELYMINIMAL"的效果,或者用Python的CSV模块得到一个固定宽度、用空格分隔的CSV输出呢?
我想要CSV文件的固定宽度特性是为了更好地阅读。这样在读取和写入时都能作为CSV处理,但由于列的结构,阅读起来会更清晰。读取没有问题,因为csv的skipinitialspace选项可以忽略多余的空格。令我惊讶的是,写入似乎成了一个问题……
编辑:我得出的结论是,使用当前的csv插件是不可能实现的。这不是一个内置选项,我也看不出有什么合理的方法可以手动实现,因为似乎没有办法通过Python的csv写入器写入额外的分隔符而不使用引号或转义字符。因此,我可能得自己写一个csv写入器。
3 个回答
这个活跃状态的示例教你如何在Python中输出表格格式的数据:
http://code.activestate.com/recipes/267662-table-indentation/
你可能能从这个例子中获取到足够的信息,来完成你想做的事情。
这对你有什么帮助呢?我觉得你其实只是缺少了 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 方言示例的一个修改。
你遇到的基本问题是,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()
当然,你需要确保所有数据的长度都是一致的,这可以在进入处理这些数据的函数之前,或者在函数内部进行调整。哦,如果你有数字数据,也要考虑到它们的填充问题。