Py学习  »  Python

使用python 3中的换行符将字符串写入csv

ke0crj • 6 年前 • 3046 次点击  

在python 3.7中工作。

我目前正在从一个API(Qualys的API,获取一个报告)中提取特定的数据。它返回一个字符串,其中所有报表数据都是csv格式,每行都用\r\n'转义符指定。

(即“foo、bar、stuff \r\n、more stuff、data、report等\r\n等)

我遇到的问题是把这个字符串正确地写到一个csv文件中。在Excel中查看时,我尝试过的每一个代码迭代都会逐个单元格地写入数据,并将其附加到字符串中的任何位置\r\n而不是新行中。

(即foo bar staff \r\n more staff data report \r\n 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()

我还尝试了各种方法来声明新行,例如:

newline=''
newline='\n'
etc...

以及沿着这些线的各种其他迭代。任何建议或指导,或…在这一点上,任何事情都是了不起的。

编辑:

好吧,我一直在努力,这有点管用:

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行,可能是某个位置的格式错误….),但更令人关注的是,当数据中出现一个“\”时,它的工作会很不稳定。

我真的会对一个有效的解决方案感兴趣…更好?更多的蟒蛇?更始终如一的方法是…

有什么想法吗?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30658
 
3046 次点击  
文章 [ 4 ]  |  最新文章 6 年前
tdelaney
Reply   •   1 楼
tdelaney    6 年前

python字符串使用 \n 换行符。通常情况下,A \r\n 转换为 \n 读取文件时 换行符被转换了 \n \rn 取决于您的系统默认值和 newline= 写入时的参数。

在你的情况下, \r 从Web界面读取时未被删除。打开文件时 newline='\r\n' ,python扩展了 \n 本来应该的,但是 R 通过,现在你的Neline是 \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'

注意,我使用了系统默认编码,但您可能希望对编码进行标准化。

Dougyfresh
Reply   •   2 楼
Dougyfresh    6 年前

看看这个答案:

Python csv string to array

根据csvreader的文档,默认情况下,它需要\r\n作为行分隔符。你的绳子应该可以用。如果您将字符串加载到csvreader对象中,那么您应该能够检查导出它的标准方法。

kanawha st.
Reply   •   3 楼
kanawha st.    6 年前

如果我正确理解了你的问题,你就不能把绳子换掉吗? with open(title, 'w') as f: f.write(res.replace("Â¥rÂ¥n","Â¥n"))

ShadowRanger
Reply   •   4 楼
ShadowRanger    6 年前

根据您的评论,您正在接受的数据实际上不包括回车或换行,它包括表示 逃逸 对于回车和换行(所以它实际上有一个反斜杠, r 反斜杠, n 在数据中)。它已经在你想要的形式中了,所以你不需要涉及 csv 模块中,只需解释转义到正确的值,然后直接写入数据。

这是相对简单的使用 unicode-escape 编解码器(也处理ASCII转义):

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)

如果收到的字符串实际上是用引号括起来的(所以 print(repr(s)) 包括两端的引号),它们可能被解释为JSON字符串。在这种情况下,只需更换 import 创造 decoded 用:

import json


decoded = json.loads(res)