Python 2和3 csv模块文本二进制模式向后兼容

时间:2019-05-19 08:56:34

标签: python python-3.x python-2.7 csv backwards-compatibility

我想创建一个与Python 2.7-3.6兼容的代码,我试图解决csv模块的问题,最初我在Python 2.7中使用0[{Last=...,Foo=...}] 1[{Last=...,Foo=...}] 2[{Last=...,Foo=...}] 3[{Last=...,Foo=...}] 4[{Last=...,Foo=...}] 5[{Last=...,Foo=...}] ,现在我必须使用outfile=open('./test.csv','wb') like in this question,否则会导致 outfile=open('./test.csv','w')

我正在使用以下代码对其进行修复:

TypeError: a bytes-like object is required, not 'str'

不太好,如果使用Python 2.7并在import sys w = 'w' if sys.version_info[0] < 3: w = 'wb' # Where needed outfile=open('./test.csv',w) 中使用Python 3.x,是否有更好的解决方案在'wb'中打开文件?为了澄清我必须在Python 2.7中使用w,因为否则,每次向文件中添加新行时,我都会有一个空白行。

1 个答案:

答案 0 :(得分:2)

python 3 上打开要与模块csv一起使用的文件时,总是应在打开语句中添加newline=""

import sys
mode = 'w'
if sys.version_info[0] < 3:
   mode  = 'wb'

# python 3 write 
with open("somefile.txt", mode, newline="") as f:
    pass  # do something with f

newline参数在python 2中不存在-但是,如果在 python 3 中跳过该参数,则在带有附加空行的Windows上将得到变形的csv输出在里面。

请参见csv.writer (python 3)

  

如果 csvfile 是文件对象,则应使用newline=''打开它。如果未指定newline='',则不会正确解释加引号的字段中嵌入的换行符,并且在使用\r\n linding编写的平台上,将添加额外的\r。指定newline=''应该总是安全的,因为 csv模块会执行自己的(通用)换行符处理。


您还应该使用上下文管理with

with open("somefile.txt", mode) as f:  # works in 2 and 3
    pass  # do something with f

即使遇到某种异常也可以关闭文件句柄。这是python 2安全的-参见Methods of file objects

  

在处理文件对象时,最好使用with关键字。这样做的好处是,即使在执行过程中引发了异常,文件在其套件完成后也将正确关闭。它也比编写等效的try-finally块要短得多。


您的解决方案-丑陋但可行:

import sys
python3 = sys.version_info[0] >= 3 

if python3:
    with open("somefile.txt","w",newline="") as f:
        pass
else:
    with open("somefile.txt","wb") as f:
        pass

问题是参数 newline在python 2中不存在。要解决此问题,您必须包装/ monkypath open(..),包括上下文管理。