【问题标题】:How to use unidecode in python (3.3)如何在 python (3.3) 中使用 unidecode
【发布时间】:2013-11-04 16:00:10
【问题描述】:

我正在尝试从文本文档中删除所有非 ascii 字符。我找到了一个可以做到这一点的包,https://pypi.python.org/pypi/Unidecode

它应该接受一个字符串并将所有非 ascii 字符转换为最接近的可用 ascii 字符。我通过调用while (<input>) { $_ = unidecode($_); } 在 perl 中轻松使用了相同的模块,这是 perl 模块的直接端口,文档表明它应该可以正常工作。

我确定这很简单,我只是对字符和文件编码了解不够,无法知道问题所在。我的 origfile 以 UTF-8 编码(从 UCS-2LE 转换而来)。这个问题可能更多地与我缺乏编码知识和处理错误的字符串有关,而不是模块,希望有人能解释原因。我已经尝试了我所知道的一切,而不仅仅是随机插入代码并搜索我到目前为止没有运气的错误。

这是我的蟒蛇

from unidecode import unidecode

def toascii():
    origfile = open(r'C:\log.convert', 'rb')
    convertfile = open(r'C:\log.toascii', 'wb')

    for line in origfile:
        line = unidecode(line)
        convertfile.write(line)

    origfile.close()
    convertfile.close()

toascii();

如果我没有以字节模式 (origfile = open('file.txt','r') 打开原始文件,那么我会从 for line in origfile: 行收到错误 UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 1563: character maps to <undefined>

如果我以字节模式打开它'rb',我会从line = unidecode(line) 行得到TypeError: ord() expected string length 1, but int found

如果我将 line 声明为字符串line = unidecode(str(line)),那么它将写入文件,但是......不正确。 \r\n'b'\xef\xbb\xbf[ 2013.10.05 16:18:01 ] User_Name > .\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\ 它正在写出 \n、\r 等和 unicode 字符,而不是将它们转换成任何东西。

如果我如上所述将行转换为字符串,并以字节模式打开转换文件'wb',则会出现错误TypeError: 'str' does not support the buffer interface

如果我以字节模式打开它而不将其声明为字符串 'wb'unidecode(line),那么我会再次收到 TypeError: ord() expected string length 1, but int found 错误。

【问题讨论】:

    标签: python unicode encoding


    【解决方案1】:

    unidecode 模块接受 unicode 字符串值并返回 Python 3 中的 unicode 字符串。您正在给它二进制数据。解码为 un​​icode 或以文本模式打开输入文本文件,并将结果编码为 ASCII,然后再将其写入文件,或以文本模式打开输出文本文件。

    引用模块文档:

    模块导出一个函数,该函数接受一个 Unicode 对象 (Python 2.x) 或 字符串 (Python 3.x) 并返回一个字符串 (可以编码为 ASCII 字节在 Python 3.x 中)

    强调我的。

    这应该可行:

    def toascii():
        with open(r'C:\log.convert', 'r', encoding='utf8') as origfile, open(r'C:\log.toascii', 'w', encoding='ascii') as convertfile:
            for line in origfile:
                line = unidecode(line)
                convertfile.write(line)
    

    这将以文本方式打开输入文件(使用 UTF8 编码,根据您的示例行判断是正确的)并以文本方式写入(编码为 ASCII)。

    您确实需要明确指定要打开的文件的编码;如果您省略编码,则使用当前系统区域设置(locale.getpreferredencoding(False) 调用的结果),如果您的代码需要可移植,这通常不是正确的编解码器。

    【讨论】:

    • @BeanBagKing:你看到的b'\xef\xbb\xbf'是一个字节值的表示;这意味着您传递的是 str(bytevalue) 的结果,而不是从输入文件解码的 unicode 字符串值。
    • @BeanBagKing:您使用什么编解码器来解码文件?只有读取文件才能在我在此处提供的示例代码中引发 unicode 解码异常,但'charmap' codec 表示您在此处使用 UTF-8 来解码在我看来是 UTF-8 数据的内容。
    • @BeanBagKing:那么您在之前的评论中发布的异常来自哪里?顺便说一句,在任何情况下都不应该为 Python 重新编码文件。
    • @BeanBagKing:请注意,我从未说过文件不是 UTF-8 格式,只是您在评论中发布的异常not与解码错误一致UTF-8 数据被解码为 UTF-8。相反,您似乎正在尝试将 UTF-8 数据解码为其他一些编解码器。
    • 对于其他想知道并阅读此内容的人来说,讨论继续进行,根本问题最终是 python 3 默认情况下不以 utf8 打开文件。原始文件必须以 utf8 编码显式打开,转换后的文件必须以 ascii 编码打开。谢谢马丁。
    猜你喜欢
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多