我想解析一个使用非ascii分隔符的类似csv的文件。 csv模块允许我设置引号字符和字段分隔符。是否可以设置记录分隔符的结尾,以便它可以与csv模块一起使用?
取一个类似csv的文件,而不是:
'"', ',', '\n'
它使用
'¦', '¶', '§'
例如
data = [
[1,r'''text "could" be
'tricky'\\'''],
[2,r'or easy']
]
将表示为
'1¶¦text "could" be\n\'tricky\'\\\\¦§2¶¦or easy¦'
我知道如何使用split等解决这个问题。但是csv模块有更好的方法吗?
此表达式生成示例:
chr(167).join(
[
chr(182).join(
[
'\xa6{}\xa6'.format(val) if type(val)==str else str(val)
for val in row
]
) for row in data
])
答案 0 :(得分:3)
不,您不能直接使用csv.reader()
,因为Dialect.lineterminator
parameter是硬编码的:
注意:
reader
是硬编码的,可以将'\r'
或'\n'
识别为行尾,并忽略lineterminator
。这种行为将来可能会改变。
您必须在阅读器周围创建一个包装器来翻译您的行终止符:
class LineTerminatorTranslator(object):
def __init__(self, orig, terminator, buffer=2048):
self._orig = orig
self._terminator = terminator
self._buffer = buffer
def __iter__(self):
terminator = self._terminator
buffer = ''
if hasattr(self._orig, 'read'):
# read in chunks, rather than in lines, where possible
iterator = iter(lambda: self._orig.read(self._buffer), '')
else:
iterator = iter(self._orig)
while True:
try:
while terminator not in buffer:
buffer += next(iterator)
except StopIteration:
# done, yield remainder
yield buffer
return
entries, _, buffer = buffer.rpartition(terminator)
for entry in entries.split(terminator):
yield entry
以2kb(可配置)的块读取输入文件,并按给定的行终止符拆分行。
因为csv.reader()
可以处理任何迭代,所以代码也可以接受其他迭代,但是如果这样的迭代每次迭代都会生成大字符串,则效率会降低。
代码应该适用于Python 2和3。
演示:
>>> import csv
>>> import io
>>> sample = '1¶¦text "could" be\'tricky\n\'\\\\¦§2¶¦or easy¦'
>>> input = LineTerminatorTranslator(io.StringIO(sample), '§')
>>> list(csv.reader(input, delimiter='¶', quotechar='¦'))
[['1', 'text "could" be\'tricky\n\'\\\\'], ['2', 'or easy']]
有点人为的Python 2版本:
>>> import csv
>>> from cStringIO import StringIO
>>> sample = '1P|text "could" be\'tricky\n\'\\\\|T2P|or easy|'
>>> input = LineTerminatorTranslator(StringIO(sample), 'T')
>>> list(csv.reader(input, delimiter='P', quotechar='|'))
[['1', 'text "could" be\'tricky\n\'\\\\'], ['2', 'or easy']]
答案 1 :(得分:1)
您无法使用csv
模块阅读此类文件。有一个名为lineterminator
的选项,但documentation表示:
读者硬编码识别'\ r'或'\ n'作为行尾,并忽略lineterminator。这种行为将来可能会改变。
您显然可以使用此lineterminator
参数编写此类文件,但您无法使用csv
模块将其读回。