首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UnicodeDecodeError在Python中读取文件时,如何忽略错误并跳到下一行?

UnicodeDecodeError在Python中读取文件时,如何忽略错误并跳到下一行?
EN

Stack Overflow用户
提问于 2014-07-08 01:49:26
回答 1查看 63.1K关注 0票数 35

我必须将一个文本文件读入Python。文件编码为:

代码语言:javascript
运行
复制
file -bi test.csv 
text/plain; charset=us-ascii

这是一个第三方文件,我每天都会得到一个新的文件,所以我宁愿不更改它。该文件包含非ascii字符,例如。我需要使用python来读取行,并且我可以忽略包含非ascii字符的行。

我的问题是,当我在Python中读取文件时,当到达存在非ascii字符的行时会得到UnicodeDecodeError,并且我无法读取文件的其余部分。

有没有办法避免这种情况。如果我尝试这样做:

代码语言:javascript
运行
复制
fileHandle = codecs.open("test.csv", encoding='utf-8');
try:
    for line in companiesFile:
        print(line, end="");
except UnicodeDecodeError:
    pass;

然后,当遇到错误时,for循环结束,我无法读取文件的其余部分。我想跳过导致错误的那一行,然后继续。如果可能的话,我宁愿不对输入文件做任何更改。

有没有办法做到这一点?非常感谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-08 02:14:12

您的文件似乎没有使用UTF-8编码。在打开文件时,使用正确的编解码器非常重要。

您可以使用errors关键字告诉open()如何处理解码错误:

错误是一个可选字符串,它指定如何处理编码和解码错误-这不能在二进制模式下使用。有多种标准错误处理程序可用,但任何已注册到codecs.register_error()的错误处理程序名称也是有效的。标准名称为:

如果存在编码错误,则使用

  • 'strict'引发ValueError异常。None的默认值具有相同的effect.
  • 'ignore'忽略错误。请注意,忽略编码错误可能会导致数据loss.
  • 'replace'导致替换标记(如'?')在存在格式错误的data.
  • 'surrogateescape'的地方插入,将把任何不正确的字节表示为从U+DC80到U+DCFF的Unicode专用区域中的代码点。然后,当在写入数据时使用surrogateescape错误处理程序时,这些私有代码点将被转换回相同的字节。这对于处理未知encoding.
  • 'xmlcharrefreplace'中的文件很有用,只有在写入文件时才支持。编码不支持的字符将替换为相应的XML字符引用&#nnn;.
  • 'backslashreplace' (仅在书写时支持)将不支持的字符替换为Python的带反斜杠的转义序列。

使用'strict'以外的任何命令('ignore''replace'等)打开文件然后将允许您读取该文件,而不会引发异常。

请注意,解码是按缓冲的数据块进行的,而不是按文本行进行的。如果必须逐行检测错误,请使用surrogateescape处理程序并测试每行读取的代理范围中的代码点:

代码语言:javascript
运行
复制
import re

_surrogates = re.compile(r"[\uDC80-\uDCFF]")

def detect_decoding_errors_line(l, _s=_surrogates.finditer):
    """Return decoding errors in a line of text

    Works with text lines decoded with the surrogateescape
    error handler.

    Returns a list of (pos, byte) tuples

    """
    # DC80 - DCFF encode bad bytes 80-FF
    return [(m.start(), bytes([ord(m.group()) - 0xDC00]))
            for m in _s(l)]

例如。

代码语言:javascript
运行
复制
with open("test.csv", encoding="utf8", errors="surrogateescape") as f:
    for i, line in enumerate(f, 1):
        errors = detect_decoding_errors_line(line)
        if errors:
            print(f"Found errors on line {i}:")
            for (col, b) in errors:
                print(f" {col + 1:2d}: {b[0]:02x}")

考虑到并不是所有的解码错误都可以从容恢复。虽然UTF-8被设计为在遇到小错误时具有健壮性,但其他多字节编码,如UTF-16和UTF-32,无法处理丢弃或额外的字节,这将影响行分隔符的精确定位。然后,上述方法会导致文件的其余部分被视为一个长行。如果文件足够大,那么在‘行’足够大的情况下,就会导致MemoryError异常。

票数 76
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24616678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档