Python2和3 csv阅读器
我试图使用csv模块读取utf-8CSV文件,但由于编码原因,我在为Python2和Python3创建通用代码时遇到了一些麻烦 以下是Python 2.7中的原始代码:Python2和3 csv阅读器,python,encoding,csv,python-3.x,Python,Encoding,Csv,Python 3.x,我试图使用csv模块读取utf-8CSV文件,但由于编码原因,我在为Python2和Python3创建通用代码时遇到了一些麻烦 以下是Python 2.7中的原始代码: with open(filename, 'rb') as csvfile: csv_reader = csv.reader(csvfile, quotechar='\"') langs = next(csv_reader)[1:] for row in csv_reader: pass
with open(filename, 'rb') as csvfile:
csv_reader = csv.reader(csvfile, quotechar='\"')
langs = next(csv_reader)[1:]
for row in csv_reader:
pass
但是当我用Python3运行它时,它不喜欢我打开文件时没有“编码”。我试过这个:
with codecs.open(filename, 'r', encoding='utf-8') as csvfile:
csv_reader = csv.reader(csvfile, quotechar='\"')
langs = next(csv_reader)[1:]
for row in csv_reader:
pass
现在python 2无法解码“for”循环中的行。所以我应该怎么做呢?事实上,在Python 2中,文件应该以二进制模式打开,而在Python 3中,文件应该以文本模式打开。(你忘了) 您必须在if块中打开文件
import sys
if sys.version_info[0] < 3:
infile = open(filename, 'rb')
else:
infile = open(filename, 'r', newline='', encoding='utf8')
with infile as csvfile:
...
导入系统
如果系统版本信息[0]<3:
infle=open(文件名为'rb')
其他:
infle=open(文件名为'r',换行符为''',编码为'utf8')
使用内嵌作为csvfile:
...
我知道一个老问题,但我正在考虑如何做到这一点。以防万一有人过来,可能会发现它很有用 这就是我解决问题的方法,谢谢Lennart Regebro的提示:
if sys.version > '3':
rd = csv.reader(open(input_file, 'r', newline='',
encoding='iso8859-1'), delimiter=';', quotechar='"')
else:
rd = csv.reader(open(input_file, 'rb'), delimiter=';',
quotechar='"')
然后做你需要做的事情:
for row in rd:
......
更新:当我的原始答案中的代码起作用时,我同时发布了一个小软件包,它为Python 2提供了一个类似Python 3的接口。因此,独立于Python版本,您只需执行
import csv342 as csv
import io
with io.open('some.csv', 'r', encoding='utf-8', newline='') as csv_file:
for row in csv.reader(csv_file, delimiter='|'):
print(row)
原始答案:这里有一个解决方案,即使使用Python2,也可以将文本解码为Unicode字符串,从而使用UTF-8以外的编码
下面的代码定义了一个函数csv\u rows()
,该函数将文件内容作为列表序列返回。用法示例:
对于csv_行中的行('some.csv',encoding='iso-8859-15',delimiter='|'):
打印(行)
以下是csv_rows()的两个变体:一个用于Python3+,另一个用于Python2.6+。在运行时,它会自动选择合适的变量UTF8Recoder
和UnicodeReader
是的逐字副本
导入csv
输入io
导入系统
如果系统版本信息[0]>=3:
#Python3变体。
def csv_行(csv_路径、编码,**关键字):
将io.open(csv_路径'r',换行符='',编码=编码)作为csv_文件:
对于csv.reader(csv_文件,**关键字)中的行:
产量行
其他:
#Python2变体。
导入编解码器
UTF8类记录器:
"""
迭代器,读取编码流并将输入重新编码到UTF-8
"""
定义初始化(self,f,encoding):
self.reader=codecs.getreader(编码)(f)
定义(自我):
回归自我
def next(自我):
返回self.reader.next().encode(“utf-8”)
类UnicodeReader:
"""
一个CSV阅读器,它将在CSV文件“f”中的行上进行迭代,
以给定的编码方式进行编码。
"""
def _uinit _;(self,f,方言=csv.excel,encoding=“utf-8”,**kwds):
f=UTF8Recoder(f,编码)
self.reader=csv.reader(f,方言=方言,**kwds)
def next(自我):
row=self.reader.next()
返回[unicode(s,“utf-8”)表示第行中的s]
定义(自我):
回归自我
def csv_行(csv_路径,编码,**kwds):
使用io.open(csv_路径,'rb')作为csv_文件:
对于UnicodeReader中的行(csv_文件,encoding=encoding,**kwds):
产量行
那么您想要在Python 2.7和3上运行不变的代码吗?可能不可能,因为字符串处理等发生了如此多的变化。是否可以为python 2或3指定块代码?您可以检查sys.version
,并在代码周围包装一个if-else
语句,是的。@Tim pietzhker;请求原谅比请求允许要好。我想你在错误的示例中使用了b标志,我把它换了过来。你能用文件句柄上的做吗?@Tim:这不是文件句柄,它是文件对象,你可以用文件对象上的
做。这正是你使用open(…
)进行操作时所做的。这是有道理的。你从来没有这样看过,文档中总是使用open(…)
进行,但这种方式还不错-使你能够包装open()
在中尝试阻塞并捕获未找到的文件
等,然后用块将其交给。或者,在某些情况下,如果sys.version<'3':open=codecs。open
@agf:是的,这也可以工作。codecs.open和Python 3 open并不完全相同,尽管存在微妙的陷阱,但通常也可以工作.在2.6和2.7中,您可以从io导入打开执行。