ChatGPT解决这个技术问题 Extra ChatGPT

将Unicode文本写入文本文件?

我正在从 Google 文档中提取数据,对其进行处理,然后将其写入文件(最终我将粘贴到 Wordpress 页面中)。

它有一些非 ASCII 符号。如何安全地将这些转换为可在 HTML 源代码中使用的符号?

目前,我正在将所有内容转换为 Unicode,将它们全部连接到 Python 字符串中,然后执行以下操作:

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

最后一行出现编码错误:

UnicodeDecodeError:“ascii”编解码器无法解码位置 12286 中的字节 0xa0:序数不在范围内(128)

部分解决方案:

这个 Python 运行没有错误:

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"))

但是,如果我打开实际的文本文件,我会看到很多符号,例如:

Qur’an 

也许我需要写入文本文件以外的东西?

您用来打开它的程序没有正确解释 UTF-8 文本。它应该有一个以 UTF-8 格式打开文件的选项。

q
quasistoic

尽可能多地专门处理 unicode 对象,方法是在您第一次获取 unicode 对象时将它们解码为 unicode 对象,并在退出时根据需要对其进行编码。

如果您的字符串实际上是 unicode 对象,则需要先将其转换为 unicode 编码的字符串对象,然后再将其写入文件:

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

当您再次读取该文件时,您将获得一个 unicode 编码的字符串,您可以将其解码为一个 unicode 对象:

f = file('test', 'r')
print f.read().decode('utf8')

谢谢。这运行没有错误,但是如果我打开文本文件,我会看到一堆奇怪的符号:) 我需要将文本复制并粘贴到 Wordpress 页面中(不要问)。有什么方法可以实际打印那里的符号吗?我猜不是txt文件,对,但也许是别的东西?
你用什么打开文本文件?我猜你在 Windows 上,你在记事本中打开它,这对编码不太智能。当您在写字板中打开它时会发生什么?
@quasistoic 文件方法是从哪里形成的?
我需要打开二进制模式,即 f=open('test', 'wb'),如 stackoverflow.com/a/5513856/6580199 中所述 - 否则我会得到“TypeError: write() argument must be str, not bytes”
这个答案可能应该包括@david_n_lee 的答案中的open('filename', 'w', encoding='utf-8')(对于python 3)
j
jfs

在 Python 2.6+ 中,您可以使用 use io.open(),即 Python 3 上的默认值 (builtin open()):

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

如果您需要逐步编写文本(无需多次调用 unicode_text.encode(character_encoding)),可能会更方便。与 codecs 模块不同,io 模块具有适当的通用换行符支持。


伙计,我花了这么多时间才找到这个!谢谢!
这也适用于 Python 3(很明显,但仍然值得指出)。
d
david m lee

Unicode 字符串处理已经在 Python 3 中标准化。

字符已经以Unicode(32位)存储在内存中您只需要以utf-8打开文件(从内存到文件的32位Unicode到可变字节长度utf-8的转换会自动执行。)out1 =“ (嘉南大雪 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )" fobj = open("t1.txt", "w", encoding="utf-8") fobj.write(out1) fobj.close ()


但这不适用于 Python 2,对吧? (我应该说,在这个 Python 3 代码上,它看起来如此简洁合理)
它不应该在 Python 2 上工作。我们继续使用 Python 3。3 好多了。
这就是答案。这就是您正确地将 utf-8 写入文件的方式,谢谢!
@KerwinSneijders 问题是关于 Python 2.7,而不是 Python 3
不再支持 Python 2.x,越来越多的人将不再使用 python 2,并且在搜索 python 3 解决方案时会在 SO 上找到这个问题。而且我认为python 2和3都不应该有2个问题,所以因为不再支持python 2.x,这应该是新接受的答案
R
Russia Must Remove Putin

前言:你的观众会工作吗?

确保您的查看器/编辑器/终端(无论您正在与 utf-8 编码文件交互)可以读取该文件。这经常是 Windows 上的问题,例如记事本。

将Unicode文本写入文本文件?

在 Python 2 中,使用 io 模块中的 open(这与 Python 3 中的内置 open 相同):

import io

最佳实践通常使用 UTF-8 写入文件(我们甚至不必担心 utf-8 的字节顺序)。

encoding = 'utf-8'

utf-8 是最现代和最普遍可用的编码 - 它适用于所有 Web 浏览器、大多数文本编辑器(如果有问题,请参阅您的设置)和大多数终端/shell。

在 Windows 上,如果您仅限于在记事本(或其他受限查看器)中查看输出,则可以尝试 utf-16le

encoding = 'utf-16le' # sorry, Windows users... :(

只需使用上下文管理器打开它并写出您的 unicode 字符:

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

使用许多 Unicode 字符的示例

这是一个示例,它尝试将每个可能的字符映射到最多三位宽(4 是最大值,但这会有点远)从数字表示(整数)到编码的可打印输出,以及它的名称,如果可能(将其放入名为 uni.py 的文件中):

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}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.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,您将看到它。可以在 here 中找到有关类别的信息。根据计数,我们可以通过排除 Cn 和 Co 类别来改进我们的结果,这些类别没有与之关联的符号。

$ python uni.py

它将显示十六进制映射、category、符号(除非无法获取名称,因此可能是控制字符)和符号名称。例如

我建议在 Unix 或 Cygwin 上使用 less(不要将整个文件打印/分类到您的输出中):

$ less unidata

例如,将显示类似于我使用 Python 2(unicode 5.2)从中采样的以下行:

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So  ¶  PILCROW SIGN
    d0 Lu  Ð  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

我来自 Anaconda 的 Python 3.5 具有 unicode 8.0,我想大多数 3 都会。


T
Thomas Wouters

codecs.open 打开的文件是一个获取 unicode 数据、在 iso-8859-1 中对其进行编码并将其写入文件的文件。但是,您尝试编写的不是 unicode;您获取 unicode 并在 iso-8859-1 您自己 中对其进行编码。这就是 unicode.encode 方法所做的,编码 unicode 字符串的结果是一个字节串(一个 str 类型)。

您应该使用普通的 open() 并自己编码 unicode,或者(通常是一个更好的主意)使用 codecs.open()not 自己编码数据。


E
Eric Leschinski

如何将 unicode 字符打印到文件中:

将此保存到文件:foo.py:

#!/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: é')

运行它并将输出通过管道传输到文件:

python foo.py > tmp.txt

打开 tmp.txt 并查看内部,您会看到:

el@apollo:~$ cat tmp.txt 
e with obfuscation: é

因此,您已将带有混淆标记的 unicode e 保存到文件中。


我对这个答案感到非常兴奋,但它在我的机器上给出了一个错误。当我复制/粘贴您的代码时,出现错误:“TypeError: must be str, not bytes”
T
Thomas K

当您尝试对非 unicode 字符串进行编码时会出现该错误:它会尝试对其进行解码,假设它是纯 ASCII 格式。有两种可能:

您将其编码为字节串,但由于您使用了 codecs.open,因此 write 方法需要一个 unicode 对象。因此,您对其进行编码,然后它会尝试再次对其进行解码。尝试: f.write(all_html) 代替。 all_html 实际上不是一个 unicode 对象。当您执行 .encode(...) 时,它首先尝试对其进行解码。


a
ashish14

在用python3编写的情况下

>>> 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中编写的情况下:

>>> 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”将其编码为字节,如下所示:

>>> f.write(a.encode("utf-8"))
>>> f.close()

并在使用编解码器“utf-8”读取时解码数据:

>>> data = open("/tmp/test").read()
>>> data.decode("utf-8")
u'bats\xe0'

而且,如果您尝试在此字符串上执行打印,它将使用像这样的“utf-8”编解码器自动解码

>>> print a
batsà

收到此错误对我不起作用:TypeError: write() argument must be str, not bytes