在Python 3和Python 2中处理CSV中的非UTF8字符

迈克91

我有以下代码可以读取csv文件(有些包含非UTF8字符)。它在Python 2.7.x中运行良好:

    encodings = {'ukprocessed.csv': 'utf8',
                 'usprocessed.csv': 'utf8',
                 'uyprocessed.csv': 'latin1',
                 'arprocessed.csv': 'latin1'}

    with codecs.open(filepath, 'r') as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            row = [x.decode(encodings[filename]).encode('utf8') for x in row]

但是,在Python 3.4.x中,测试失败并产生各种错误:

  • AttributeError:“ str”对象没有属性“ decode”
  • UnicodeDecodeError:'ascii'编解码器无法解码位置1078的字节0xf1:序数不在range(128)等范围内...

我已经在打开的文件中指定了'encoding =',用'rb'作为字节以其他方式打开,但我找不到在Python 2和3中都可以使用的解决方案。

有人对我该如何解决有任何想法吗?

谢谢

暗影游侠

狭义地解决错误的原因:

在Py3中,x每个值row都是str(类似于Py2 unicode)。在Py2中,strunicode太灵活了,因为str它既是文本数据类型又是二进制数据类型。encode通过假设str是ASCII来支持某种解码,然后将其重新编码为选定的编码(对于ASCII兼容编解码器而言,这毫无意义,因为遇到非ASCII时会出错)。对于对称性,允许类似的容易出错且类型毫无意义decode错误unicode它将转换encode为ASCII(如果unicode包含非ASCII,则会出错),然后decode在请求的编解码器中。这是各种误解,错误等的根源。

在Python 3中,他们可以更好地拆分类型:

  1. str文本类型,并且只具有一个encode方法(从逻辑字符转换为一个特定的所述字符的二进制编码)
  2. bytes(以及其他bytes类似类型的数据)代表二进制数据,并且只有一种decode方法(将特定的二进制编码转换为逻辑字符)

以可移植的方式解决您的问题:

您的代码要求支持“纯文本”类型decode(binary-> text),并且正如我所指出的那样,Py2在有限的意义上允许这样做,即使它通常很笨。Py3不会;decode-将逻辑文本转换为逻辑文本是荒谬的,并且为了避免无声的错误行为,Py3不提供无效的方法(Py2会根据unicode对象的内容工作,然后在错误时失败;您会认为代码不是-英语友好,如果您将其与非英语文本一起实际使用,则会中断)。

csv如果您需要完全的可移植性,那么编写必须处理非ASCII类型的代码并非易事。这是问题所在:

  1. 在Python 2中,您必须使用str(面向字节的)编码方式,该编码方式不包含Embedded NUL,而不是unicode注意: unicode如果仅包含由返回的编码中的文本,则碰巧会起作用sys.getdefaultencoding(),因为csv通常使用asciisite模块启动时使用值配置的值文本进行静默编码sys.setdefaultencoding调用后site删除sys.setdefaultencoding,您不应该自己对其进行调整;当输入csv从强制转换unicode时,输入内容不符合语言环境编码时,它会中断str这也不仅仅取决于您的系统区域设置。我的系统,使用上LANG=en_US.latin-1LANG=en_US.utf-8,Python是回国还是'ascii'我的sys.getdefaultencoding()
  2. 在Python 3中,您必须使用str(面向文本,相当于Py2的unicode

通常,对于不csv相关的情况,我建议使用纯粹基于文本的类型io.open来获得Py2.7和Py3.x之间的完全兼容性(以及比更好的性能/兼容性codecs.open)。但是io.opencodecs.open就此而言)在文本模式下会返回unicodePy2(csv除非可以使用默认编码表示否则无法使用,因此您会认为它可以工作,直到您提供默认编码无法处理的内容为止),并且str在Py3中(精细);在二进制模式下,它返回str上的Py2(罚款,如果没有内嵌NULS,虽然它不是解码你,所以你需要两个解码来自strunicode从,然后编码背unicodeutf-8 str),并bytes在PY3(需要被解码str) 。它很丑。

我能提供的最佳解决方案是使用io.open,但在特定步骤产生的迭代器周围添加一个与版本相关的包装器,以确保该迭代器的输出具有给定Python版本(以Py2,Py3utf-8编码)的适当形式。您保持一致的行为(并将版本检查限制为每个文件执行固定次数,而不是每行执行一次):strstr

import io
import sys

encodings = {'ukprocessed.csv': 'utf8',
             'usprocessed.csv': 'utf8',
             'uyprocessed.csv': 'latin1',
             'arprocessed.csv': 'latin1'}

# io.open in text mode will return unicode on Py2, str on Py3, decoded appropriately
# newline='' prevents it from doing line ending conversions (which are csv's
# responsibility)
with io.open(filepath, encoding=encodings[filepath], newline='') as csvdata:
    if sys.version_info[0] == 2:
        # Lazily convert lines from unicode to utf-8 encoded str
        csvdata = (line.encode('utf-8') for line in csvdata)
    reader = csv.reader(csvdata)
    if sys.version_info[0] == 2:
        # Decode row values to unicode on Py2; they're already str in Py3
        reader = ([x.decode('utf-8') for x in row] for row in reader)
    for row in reader:
        # operate on row containing native text types as values that can
        # represent whole Unicode range (unicode on Py2, str on Py3)
        ...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Python 3中,如何从字符串中删除所有非UTF8字符?

来自分类Dev

如何在python中构建utf8字符串

来自分类Dev

用Python计算UTF8字符

来自分类Dev

在python 2.7中打印UTF-8字符

来自分类Dev

如何删除python字符串的最后utf8字符

来自分类Dev

在python 3中将转义的utf-8字符串转换为utf

来自分类Dev

python用3个字节的utf8字符拆分unicode字符串

来自分类Dev

Python将UTF8字符串插入SQLite

来自分类Dev

utf-8字符串从python到AWS中的Java android

来自分类Dev

Swift UTF8编码和非UTF8字符

来自分类Dev

使用python将utf-8字符串保存到sqlite表中(sqlite3模块)

来自分类Dev

UTF-8无法在我的python代码中编码UTF-8字符。它们显示为原义UTF-8

来自分类Dev

我必须使用哪种python编码类型来读取非utf-8字符?

来自分类Dev

使用Python curses将UTF8字符写入屏幕的最后一个位置

来自分类Dev

在Python中的字符串中查找utf8子字符串的位置

来自分类Dev

插入utf-8字符串时出现python和sqlite3.ProgrammingError

来自分类Dev

python 3中的字节流和utf-8

来自分类Dev

Python 3多处理和套接字

来自分类Dev

在Python 3.5中编码utf-8和utf8之间的区别

来自分类Dev

无法转换UTF-8字符-Python

来自分类Dev

Python反转UTF-8字符串

来自分类Dev

如何通过Python 3中作为命令行参数提供的转义序列来拆分UTF-8字符串?

来自分类Dev

为什么我无法在python2.7中解码'utf8'字符串?

来自分类Dev

为什么我无法在python2.7中解码'utf8'字符串?

来自分类Dev

Python 2和3中的评估范围

来自分类Dev

Powershell中的Python 2和3

来自分类Dev

Powershell中的Python 2和3

来自分类Dev

Powershell中的Python 2和3

来自分类Dev

Python 3.3 C-API和UTF-8字符串

Related 相关文章

热门标签

归档