Writing Unicode text to a text file?
我正在从谷歌文档中提取数据,并对其进行处理,然后将其写入一个文件(最终我将粘贴到WordPress页面中)。
它有一些非ASCII符号。如何将这些安全地转换为可在HTML源代码中使用的符号?
目前,我正在将所有内容转换为unicode,将其连接到一个python字符串中,然后执行以下操作:
1 2 3 | import codecs f = codecs.open('out.txt', mode="w", encoding="iso-8859-1") f.write(all_html.encode("iso-8859-1","replace")) |
最后一行出现编码错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position
12286: ordinal not in range(128)
部分溶液:
此python运行时没有出错:
1 2 3 4 | row = [unicode(x.strip()) if x is not None else u'' for x in row] all_html = row[0] +"<br/>" + row[1] f = open('out.txt', 'w') f.write(all_html.encode("utf-8") |
但是如果我打开实际的文本文件,我会看到很多符号,比如:
1 | Qur???an |
也许我需要写一些文本文件以外的东西?
当您第一次得到Unicode对象时,通过将其解码为Unicode对象,并在退出时根据需要对其进行编码,尽可能地专门处理Unicode对象。
如果字符串实际上是Unicode对象,则在将其写入文件之前,需要将其转换为Unicode编码的字符串对象:
1 2 3 4 | foo = u'Δ, Й, ?, ? ?, ?, あ, 叶, 葉, and ?.' f = open('test', 'w') f.write(foo.encode('utf8')) f.close() |
当您再次读取该文件时,您将得到一个Unicode编码的字符串,您可以将其解码为Unicode对象:
1 2 | f = file('test', 'r') print f.read().decode('utf8') |
在python 2.6+中,可以使用
1 2 3 4 | import io with io.open(filename, 'w', encoding=character_encoding) as file: file.write(unicode_text) |
如果需要增量地编写文本(不需要多次调用
Unicode字符串处理在Python3中是标准化的。
您只需要以UTF-8格式打开文件
1 2 3 4 | out1 ="(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )" fobj = open("t1.txt","w", encoding="utf-8") fobj.write(out1) fobj.close() |
由
您应该使用普通的
前言:你的观众会工作吗?
确保您的查看器/编辑器/终端(但是您正在与UTF-8编码文件交互)可以读取该文件。这通常是Windows上的一个问题,例如记事本。
Writing Unicode text to a text file?
在python 2中,使用来自
1 | import io |
一般来说,最佳实践是使用
1 | encoding = 'utf-8' |
UTF-8是最现代和最通用的编码方式——它适用于所有Web浏览器、大多数文本编辑器(如果有问题,请参阅您的设置)和大多数终端/外壳。
在Windows上,如果您仅限于在记事本(或其他有限的查看器)中查看输出,则可以尝试使用
1 | encoding = 'utf-16le' # sorry, Windows users... :( |
只需使用上下文管理器打开它并写出您的Unicode字符:
1 2 | with io.open(filename, 'w', encoding=encoding) as f: f.write(unicode_object) |
使用许多Unicode字符的示例
下面是一个示例,它尝试将每个可能的字符映射到3位宽(4是最大值,但这可能会有点远),从数字表示(整数)到编码的可打印输出,如果可能的话,还包括其名称(将其放入名为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | from __future__ import print_function import io from unicodedata import name, category from curses.ascii import controlnames from collections import Counter try: # use these if Python 2 unicode_chr, range = unichr, xrange except NameError: # Python 3 unicode_chr = chr exclude_categories = set(('Co', 'Cn')) counts = Counter() control_names = dict(enumerate(controlnames)) with io.open('unidata', 'w', encoding='utf-8') as f: for x in range((2**8)**3): try: char = unicode_chr(x) except ValueError: continue # can't map to unicode, try next x cat = category(char) counts.update((cat,)) if cat in exclude_categories: continue # get rid of noise & greatly shorten result file try: uname = name(char) except ValueError: # probably control character, don't use actual uname = control_names.get(x, '') f.write(u'{0:>6x} {1} {2} '.format(x, cat, uname)) else: f.write(u'{0:>6x} {1} {2} {3} '.format(x, cat, char, uname)) # may as well describe the types we logged. for cat, count in counts.items(): print('{0} chars of category, {1}'.format(count, cat)) |
这应该以大约一分钟的顺序运行,您可以查看数据文件,如果文件查看器可以显示Unicode,您将看到它。有关类别的信息可在此处找到。基于计数,我们可能可以通过排除没有相关符号的cn和co类别来改进结果。
1 | $ python uni.py |
它将显示十六进制映射、类别、符号(除非无法获得名称,所以可能是控制字符)和符号的名称。例如
我建议在Unix或Cygwin上使用
1 | $ less unidata |
例如,将显示类似于我使用python 2(unicode 5.2)从中采样的以下行:
1 2 3 4 5 6 7 8 9 | 0 Cc NUL 20 Zs SPACE 21 Po ! EXCLAMATION MARK b6 So ? PILCROW SIGN d0 Lu D LATIN CAPITAL LETTER ETH e59 Nd ? THAI DIGIT NINE 2887 So ? BRAILLE PATTERN DOTS-1238 bc13 Lo ? HANGUL SYLLABLE MIH ffeb Sm ? HALFWIDTH RIGHTWARDS ARROW |
我的Python3.5有Unicode8.0,我想大多数3的都有。
如何将Unicode字符打印到文件中:
将此保存到文件:foo.py:
1 2 3 4 5 6 7 | #!/usr/bin/python -tt # -*- coding: utf-8 -*- import codecs import sys UTF8Writer = codecs.getwriter('utf8') sys.stdout = UTF8Writer(sys.stdout) print(u'e with obfuscation: é') |
运行它并将输出管道传输到文件:
1 | python foo.py > tmp.txt |
打开tmp.txt查看内部,您会看到:
1 2 | el@apollo:~$ cat tmp.txt e with obfuscation: é |
因此,您已经将带有模糊标记的Unicode E保存到一个文件中。
当您试图对一个非Unicode字符串进行编码时,就会出现这个错误:它试图对其进行解码,假设它是纯ASCII格式的。有两种可能性:
如果写信给python3
1 2 3 4 5 6 7 8 9 | >>> a = u'bats\u00E0' >>> print a batsà >>> f = open("/tmp/test","w") >>> f.write(a) >>> f.close() >>> data = open("/tmp/test").read() >>> data 'batsà' |
如果写信给python2:
1 2 3 4 5 6 7 | >>> a = u'bats\u00E0' >>> f = open("/tmp/test","w") >>> f.write(a) Traceback (most recent call last): File"<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128) |
要避免此错误,您必须使用编码解码器"utf-8"将其编码为字节,如下所示:
1 2 | >>> f.write(a.encode("utf-8")) >>> f.close() |
并在读取时使用编解码器"utf-8"对数据进行解码:
1 2 3 | >>> data = open("/tmp/test").read() >>> data.decode("utf-8") u'bats\xe0' |
而且,如果您尝试在这个字符串上执行print,它将自动使用类似这样的"utf-8"编解码器进行解码。
1 2 | >>> print a batsà |