当记录结束标记不是新行时,我可以使用 csv 模块吗?
can I use the csv module when the end of record marker is not a new line?
我想解析一个使用非 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
])
您无法使用 csv
模块读取此类文件。有一个名为 lineterminator
的选项,但 documentation 表示:
The reader is hard-coded to recognise either '\r' or '\n' as end-of-line, and ignores lineterminator. This behavior may change in the future.
您显然可以使用此 lineterminator
参数来 写入 这样的文件,但您无法使用 csv
模块。
不,您不能为此直接使用 csv.reader()
,因为 Dialect.lineterminator
parameter 是硬编码的:
Note: The reader
is hard-coded to recognise either '\r'
or '\n'
as end-of-line, and ignores lineterminator
. This behavior may change in the future.
您必须围绕 reader 创建一个包装器来翻译您的行终止符:
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']]
略做作Python2版本:
>>> 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']]
我想解析一个使用非 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
])
您无法使用 csv
模块读取此类文件。有一个名为 lineterminator
的选项,但 documentation 表示:
The reader is hard-coded to recognise either '\r' or '\n' as end-of-line, and ignores lineterminator. This behavior may change in the future.
您显然可以使用此 lineterminator
参数来 写入 这样的文件,但您无法使用 csv
模块。
不,您不能为此直接使用 csv.reader()
,因为 Dialect.lineterminator
parameter 是硬编码的:
Note: The
reader
is hard-coded to recognise either'\r'
or'\n'
as end-of-line, and ignoreslineterminator
. This behavior may change in the future.
您必须围绕 reader 创建一个包装器来翻译您的行终止符:
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']]
略做作Python2版本:
>>> 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']]