如何使用Python将文件格式从Unicode转换为ASCII?

24

我使用一个第三方工具输出Unicode格式的文件,但我更喜欢它是ASCII格式。该工具没有更改文件格式的设置。

使用Python转换整个文件格式的最佳方法是什么?

8个回答

44
你可以轻松地使用unicode函数进行文件转换,但是如果Unicode字符没有与直接ASCII等价物时将会遇到问题。
这篇博客文章推荐使用unicodedata 模块,该模块似乎能够处理粗略的字符转换而不需要对应的ASCII值,例如:
>>> title = u"Klüft skräms inför på fédéral électoral große"

通常会转换为

Klft skrms infr p fdral lectoral groe

这是相当错误的。不过,使用unicodedata模块,结果可以更接近原始文本:

>>> import unicodedata
>>> unicodedata.normalize('NFKD', title).encode('ascii','ignore')
'Kluft skrams infor pa federal electoral groe'

那个还不错,只是(如注)它漏掉了一些字符。对于Latin-1,您需要特别处理Æ、Ð、Ø、Þ、æ、ð、ø、ß和þ。 - giltay
Fredrick Lundh在这篇文章中发表了自己的看法,并提供了一个简单的脚本,可在unicodedata的基础上进行特殊情况下的替换:http://effbot.org/zone/unicode-convert.htm - rcoup

11

我认为这比你意识到的要深刻得多。仅仅将文件从Unicode转换为ASCII是很容易的,但是让所有的Unicode字符都翻译成合理的ASCII对应字符(许多字母在两种编码中都不可用)则是另一个问题。

这篇Python Unicode教程可以让您更好地了解将Unicode字符串翻译成ASCII会发生什么:http://www.reportlab.com/i18n/python_unicode_tutorial.html

以下是该网站上的有用引用:

Python 1.6还提供了一个“unicode”内置函数,您可以指定编码方式:

> >>> unicode('hello') u'hello'
> >>> unicode('hello', 'ascii') u'hello'
> >>> unicode('hello', 'iso-8859-1') u'hello'
> >>>

这三种编码方式返回的内容相同,因为“Hello”中的字符在所有三种编码方式中都是通用的。

现在让我们对带有欧洲口音的内容进行编码,这是超出ASCII范围的。您在控制台上看到的内容可能取决于您的操作系统语言环境;Windows让我输入ISO-Latin-1。

> >>> a = unicode('André','latin-1')
> >>> a u'Andr\202'

如果您无法输入重音字母e, 您可以输入字符串'Andr\202', 这是无歧义的。

Unicode支持所有常见的 操作,如迭代和拆分。 我们不会在此详述。


1
感谢指出潜在的问题。然而,我不会冒险在输出文件内容中出现无法转换的Unicode字符。它只是输出内部数据库的SQL模式,不包含任何超出ASCII范围的特殊字符。 - Ray
1
@Ray Vega:就目前而言,你所知道的是这样。假设Unicode数据只包含ASCII字符是一个错误和潜在的漏洞。 - Robert P

4
顺便提一下,有一个Linux命令iconv可以完成这种工作。
iconv -f utf8 -t ascii <input.txt >output.txt

2

我遇到一个问题,我只想跳过非ASCII字符,并只输出ASCII字符,以下解决方案非常有效:

    import unicodedata
    input = open(filename).read().decode('UTF-16')
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')

2

就像这样:

uc = open(filename).read().decode('utf8')
ascii = uc.decode('ascii')

请注意,如果有任何不能转换为ASCII的字符,则此操作将失败,并引发UnicodeDecodeError异常。
编辑:正如Pete Karl所指出的那样,从Unicode到ASCII没有一对一的映射。因此,有些字符无法以保留信息的方式进行转换。此外,标准ASCII或多或少是UTF-8的子集,因此您实际上甚至不需要进行任何解码。

2

这是一些简单(且愚蠢)的代码来进行编码转换。我假设(但你不应该这么做)输入文件采用UTF-16编码(Windows将其称为“Unicode”)。

input_codec = 'UTF-16'
output_codec = 'ASCII'

unicode_file = open('filename')
unicode_data = unicode_file.read().decode(input_codec)
ascii_file = open('new filename', 'w')
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec)))

请注意,如果Unicode文件中有任何非ASCII字符,则此方法将无法正常工作。您可以执行以下操作将无法识别的字符转换为“?”:
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec, 'replace')))

查看文档以获取更简单的选择。如果您需要进行更复杂的操作,可以查看Python食谱中的UNICODE Hammer


0
正如其他帖子中提到的,ASCII是Unicode的一个子集。
然而,如果你:
- 有一个旧版应用程序 - 你无法控制该应用程序的代码 - 你确定输入属于ASCII子集
那么下面的示例展示了如何实现:
mystring = u'bar'
type(mystring)
    <type 'unicode'>

myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
    <type 'str'>

0

需要注意的是,不存在“Unicode”文件格式。 Unicode可以以多种不同的方式编码为字节。 最常见的是UTF-8或UTF-16。 您需要知道您的第三方工具输出的编码方式。 一旦您知道了这一点,转换不同的编码之间就很容易:

in_file = open("myfile.txt", "rb")
out_file = open("mynewfile.txt", "wb")

in_byte_string = in_file.read()
unicode_string = bytestring.decode('UTF-16')
out_byte_string = unicode_string.encode('ASCII')

out_file.write(out_byte_string)
out_file.close()

正如其他回答中所指出的那样,您可能需要为编码方法提供一个错误处理程序。使用“replace”作为错误处理程序很简单,但如果文本包含无法表示为ASCII的字符,则会破坏您的文本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接