【问题标题】:Parsing CSV string with CSV module使用 CSV 模块解析 CSV 字符串
【发布时间】:2021-03-09 15:13:03
【问题描述】:

我正在从外部源通过管道获取 CSV 格式的数据,并且不应将数据写入文件,这将打开许多我想避免的不同维护任务。我将数据作为字符串获取。

所以现在我想将数据解释为 CSV。 python 模块csv 适合这个,所以我正在使用它。

但是,使用 csv.reader(或 dictreader)构建 CSV 解析器需要数据支持迭代器。一个列表或一个读者已经这样做了。但是,我的数据包含引号字符串内的换行符 (\n)(这对于 CSV 格式完全没问题),以及作为记录结束指示符/行终止符的换行符。

如果我这样构造它:

csvreader = csv.reader(data.split('\n'))

然后我已经通过将换行符解释为记录结束指示符来破坏有效的 CSV 格式,即使它们在带引号的字符串内。对我来说,换行符的解释应该由 CSV 解析器完成,因为它知道引号字段包含 CSV 相关格式字符,如换行符。

我对@9​​87654328@ 包解析器的工作方式有误解吗?或者当数据包含不表示记录结束的换行符时,我将如何使用 CSV 解析器解析 CSV 类型字符串?

编辑 1:在我的问题中添加上下文可能并不明智,因为上下文似乎已经超过了我的实际问题/问题。澄清一下,我的问题是 not 从内存中解析 CSV。我已经找到StringIO。当使用StringIO 时,所做的只是使用整个字符串/文件作为第一条记录。

编辑 2:也许样本数据会有所帮助。我的数据如下所示:

"value1";"value2";"value3
stillvalue3"
"value4";"value5";"value6"

所以在第一条记录的第三个条目中我有一个换行符,它应该被解释为第一条记录中第三个条目的一部分。

编辑3:我目前使用解析器的方式是这样的:

csvreader = csv.reader(StringIO(result), quotechar='"', delimiter=';', lineterminator='\n', escapechar='"')

因为规范说字段内的双引号 (") 被引号字符 ("") 转义,因此数据可能如下所示:

"value1";"value2";"value3
stillvalue3
a ""quote"" inside the quote"
"value4";"value5";"value6"

似乎使用这些设置,StringIO 输入总是会生成一条记录,其中包含字符串中的所有数据。删除

escapechar='"'

解决了这个问题,但是,我不支持引号内的转义双引号字符。所以我的问题的性质改变了。如果有人有想法,我会保持开放状态,稍后会接受 Martin Evans 的回答。

【问题讨论】:

  • 最简单的方法是使用StringIO(现在是from io import StringIO),如下所示:stackoverflow.com/a/18724978/3001761
  • 问题是(除了escapechar)csv.reader 正确读取了您显示的唯一数据。所以我们必须猜测问题可能是什么。您必须展示一些展示问题的数据,包括您得到的和想要的。

标签: python python-3.x csv


【解决方案1】:

您可以使用 Python 的 StringIO() 为您的数据字符串提供流接口。

不要尝试使用data.split('\n'),因为这将无法正确拆分行,csv.reader() 将正确读取行,即使单元格包含换行符:

from io import StringIO
import csv

data = '''"value1";"value2";"value3
stillvalue3"
"value4";"value5";"value6"'''

csv_input = csv.reader(StringIO(data, newline=''), delimiter=';')
rows = list(csv_input)
print("Rows", rows)    

给你:

Rows [['value1', 'value2', 'value3\nstillvalue3'], ['value4', 'value5', 'value6']]

然后可以将其加载到 Pandas 中,或直接使用 StringIO():

columns = ['col1', 'col2', 'col3']

df = pd.DataFrame(rows, columns=columns)

df = pd.read_csv(StringIO(data, newline=''), names=columns, sep=';')

print(df)

给予:

     col1    col2                 col3
0  value1  value2  value3\nstillvalue3
1  value4  value5               value6

你的第二个例子给出了:

Rows [['value1', 'value2', 'value3\nstillvalue3\na "quote" inside the quote'], ['value4', 'value5', 'value6']]

     col1    col2                                             col3
0  value1  value2  value3\nstillvalue3\na "quote" inside the quote
1  value4  value5                                           value6

【讨论】:

  • 请看我的编辑。谢谢你的例子,但我上面试图描述的问题没有反映在你的例子中。
  • 我已经更新它以使用您的示例,重点不是尝试自己拆分行,而是依靠csv.reader() 正确解析它。
  • 如上所述,StringIO 确实有效,只是不适用于我使用的参数。我会保持开放一段时间,也许有人有想法,稍后接受你的回答。
  • 尝试将newline='' 参数添加到您的StringIO() 调用中,如我的示例中所示。你的第二个例子似乎对我来说很好。
  • 对 StringIO 使用建议的newline=''(而不是我正在做的,用于 CSV 解析器)就像一个魅力。正如您已经看到的,它现在可以完全正确地解析。感谢您的宝贵时间。
猜你喜欢
  • 2014-02-09
  • 2017-01-27
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 2014-09-17
  • 2021-01-08
  • 2021-03-21
  • 1970-01-01
相关资源
最近更新 更多