在python 3中使用换行符将字符串写入CSV
在Python3.7中工作 具体来说,我目前正在从API(Qualys的API,获取报告)中提取数据。它返回一个字符串,其中包含CSV格式的所有报告数据,每一行都用“\r\n”转义符指定 (即“foo、bar、stuff\r\n、more stuff、data、report\r\n等,等等\r\n”) 我遇到的问题是将此字符串正确写入CSV文件。在Excel中查看时,我尝试的每一次代码迭代都会逐个单元格写入数据,\r\n并将数据附加到字符串中的任何位置,所有数据都放在一行上,而不是放在新行上 (即| foo | bar | stuff\r\n | more stuff | data | report\r\n | etc | etc | etc\r\n |) 我只是在从2切换到3,所以我几乎可以肯定这是一个语法错误,或者是我理解python 3如何处理新行分隔符或类似于这些行的错误,但是即使在查看文档、这里和博客帖子之后,我也无法理解它,或者我一直在错过什么 当前代码:在python 3中使用换行符将字符串写入CSV,python,python-3.x,csv,newline,delimiter,Python,Python 3.x,Csv,Newline,Delimiter,在Python3.7中工作 具体来说,我目前正在从API(Qualys的API,获取报告)中提取数据。它返回一个字符串,其中包含CSV格式的所有报告数据,每一行都用“\r\n”转义符指定 (即“foo、bar、stuff\r\n、more stuff、data、report\r\n等,等等\r\n”) 我遇到的问题是将此字符串正确写入CSV文件。在Excel中查看时,我尝试的每一次代码迭代都会逐个单元格写入数据,\r\n并将数据附加到字符串中的任何位置,所有数据都放在一行上,而不是放在新行上 (
def dl_report(id, title):
data = {'action': 'fetch', 'id': id}
res = a.request('/api/2.0/fo/report/', data=data)
print(type(res)) #returns string
#input('pause')
f_csv = open(title,'w', newline='\r\n')
f_csv.write(res)
f_csv.close
但我也尝试过:
with open(title, 'w', newline='\r\n') as f:
writer = csv.writer(f,<tried encoding here, no luck>)
writer.writerows(res)
#anyone else looking at this, this didn't work because of the difference
#between writerow() and writerows()
以及沿着这些路线的各种其他迭代。任何建议或指导或。。。在这一点上做任何事情都会很棒
编辑:
好的,我一直在做这件事,这种方法很有效:
def dl_report(id, title):
data = {'action': 'fetch', 'id': id}
res = a.request('/api/2.0/fo/report/', data=data)
print(type(res)) #returns string
reader = csv.reader(res.split(r'\r\n'), delimiter=',')
with open(title, 'w') as outfile:
writer = csv.writer(outfile, delimiter= '\n')
writer.writerow(reader)
但是它很难看,并且确实在输出CSV中产生了错误(一些行(小于1%)不作为CSV行进行解析,可能是某个地方的格式错误…),但更令人担心的是,当数据中显示“\”时,它的工作不稳定
我真的对一个有效的解决方案很感兴趣。。。更好?更像蟒蛇?更一致的做法会更好
有什么想法吗 如果我没弄错你的问题,你就不能换个字符串吗?
以开放式(标题“w”)作为f:f.write(res.replace(“¥r¥n”,“¥n”))
查看以下答案:
根据CSVReader的文档,默认情况下,它需要\r\n作为行分隔符。你的绳子应该很好用。如果将字符串加载到CSVReader对象中,则应该能够检查导出该字符串的标准方法 Python字符串使用单个
\n
换行符。通常,读取文件时,\r\n
会转换为\n
根据系统默认值和写入时的换行符=
参数,换行符将被转换为\n
或\r\n
在您的情况下,从web界面读取时,\r
未被删除。当您使用换行符='\r\n'
打开文件时,python按预期扩展了\n
,但是\r
通过了,现在您的换行符是\r\n
。通过以二进制模式重新读取文本文件,您可以看到:
>>> res = 'foo,bar,stuff\r\n,more stuff,data,report\r\n,etc,etc,etc\r\n'
>>> open('test', 'w', newline='\r\n').write(res)
54
>>> open('test', 'rb').read()
b'foo,bar,stuff\r\r\n,more stuff,data,report\r\r\n,etc,etc,etc\r\r\n'
由于您已经有了所需的行尾,只需以二进制模式写入并跳过转换:
>>> open('test', 'wb').write(res.encode())
54
>>> open('test', 'rb').read()
b'foo,bar,stuff\r\n,more stuff,data,report\r\n,etc,etc,etc\r\n'
请注意,我使用了系统默认编码,但您可能希望在编码上进行标准化。根据您的评论,您正在接收的数据实际上不包括回车符或换行符,它包括表示回车符和换行符转义的文本(因此它在数据中确实有一个反斜杠,
r
,反斜杠,n
)。否则它已经是您想要的形式,所以您根本不需要涉及csv
模块,只需将转义解释为正确的值,然后直接写入数据
使用unicode转义
codec(也处理ASCII转义)相对简单:
如果您收到的字符串实际上是用引号括起来的(因此,print(repr))
在两端都包含引号),那么它们可能被解释为JSON字符串。在这种情况下,只需将import
和decoded
的创建替换为:
import json
decoded = json.loads(res)
这仍然不起作用。似乎write函数没有解释新行分隔符,无论它们是“\r\n”还是“\n”,这就是为什么我认为我处理字符串或新行函数的方式有问题。如果它已经是文本CSV,您可以直接编写它。听起来好像您在说文本包括文本反斜杠后跟
r
和n
但是,是这样吗?也就是说,如果您打印(repr(字符串))
,你看到一个反斜杠还是两个反斜杠了?@ShadowRanger两个反斜杠。我认为问题之一是api输出是CSV-ish。它包含大量的头信息,然后是多个CSV,每个头上都有一个表头。这很好地工作了!非常感谢!我在试图将其作为字符串工作时感到非常沮丧,而且从来没有这样做过我想走这条路。我根据前面的评论和其他地方尝试了一些不同的编码功能,但没有解码。简单明了的解决方案。再次感谢!
import codecs # Needed for text->text decoding
# ... retrieve data here, store to res ...
# Converts backslash followed by r to carriage return, by n to newline,
# and so on for other escapes
decoded = codecs.decode(res, 'unicode-escape')
# newline='' means don't perform line ending conversions, so you keep \r\n
# on all systems, no adding, no removing characters
# You may want to explicitly specify an encoding like UTF-8, rather than
# relying on the system default, so your code is portable across locales
with open(title, 'w', newline='') as f:
f.write(decoded)
import json
decoded = json.loads(res)