在python 3中使用换行符将字符串写入CSV

在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并将数据附加到字符串中的任何位置,所有数据都放在一行上,而不是放在新行上 (

在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如何处理新行分隔符或类似于这些行的错误,但是即使在查看文档、这里和博客帖子之后,我也无法理解它,或者我一直在错过什么

当前代码:

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)