python无法编码奇怪的字符

时间:2018-06-22 08:38:40

标签: python json python-2.7 utf-8

我正在尝试通过运行以下脚本来解析2GB以上的txt文件:

#!/usr/bin/env python
import json

def convert2json(filename):
    with open(filename) as I:
        for line in I:
            d = {"data": line}
            print(json.dumps(d, ensure_ascii=False))

if __name__ == "__main__":
    import sys

    convert2json(sys.argv[1])

脚本抛出错误:

Traceback (most recent call last):
  File "ori.py", line 13, in <module>
    convert2json(sys.argv[1])
  File "ori.py", line 8, in convert2json
    print(json.dumps(d))
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe0 in position 31: invalid continuation byte

并且处理特殊字符时失败(我相信):

<E0>ทำคาม:
:<E9>皇甫
:<E9>皇甫:<E9>皇甫:<E9>皇甫

如何使脚本仅忽略引起问题的行?

当我转到要分析的文件并复制无法处理的大部分行时,请创建一个新文件并再次运行该脚本-它将起作用。我这样做是通过将行从less复制到使用vi的文件中来完成的。复制带有编码本身的行时,我在做什么吗?

2 个答案:

答案 0 :(得分:0)

好,您正在使用Python 2,因此从文件中读取的是字节字符串。更多根据错误消息,您拥有ensure_ascii参数的默认设置,该设置为true。在这种情况下,所有字符串都将使用默认编码(utf8)进行解码。如果您输入的不是utf8编码,则会得到UnicodeDecodeError

该怎么办?

如果您不确定初始编码,只是想保留所有内容 ,则可以声明Latin1编码。它只是更改具有该代码的unicode字符中的每个字节。 ensure_ascii有点不同:它只允许结果json字符串中的任何字节,这可能导致无法移植的Json:

  

RFC并未明确禁止JSON字符串包含不与有效Unicode字符相对应的字节序列(例如,未配对的UTF-16替代),但是它确实指出,它们可能会导致互操作性问题。默认情况下,此模块接受并输出此类序列的代码点(如果存在于原始str中)。

这是一种防弹方式:

def convert2json(filename):
    with open(filename) as I:
        for line in I:
            d = {"data": line}
            print(json.dumps(d, encoding='Latin1'))

在输入文件中,例如'\x..'只是一个非ASCII字符,在Json中将被编码为'\u00..'

答案 1 :(得分:-1)

好吧,要跳过这些行,您可以使用以下代码:

#!/usr/bin/env python
import json

def convert2json(filename):
    with open(filename) as I:
        for line in I:
            try:
                d = {"data": line}
                print(json.dumps(d, ensure_ascii=False))
            except:
                continue

if __name__ == "__main__":
    import sys

    convert2json(sys.argv[1])  

我已将代码包装在try / except块中的循环中。
这样,当发生错误时,它将被忽略。您将不会看到当前行的任何输出,并且脚本将继续进行下一行。

但是,尝试使用文件的提供部分时,我的测试没有引发错误。您能告诉我们文件的编码是什么吗?您确定问题是由这些字符引起的吗?尝试添加一个 您原始代码中的print()语句和一个计数器,以便您可以识别正确的无效行。