每当我尝试读取UTF-8编码的文本文件时,即使使用open(file_name, encoding='utf-8')
,我总是会收到错误,说ascii编解码器无法解码某些字符(例如,使用for line in f: print(line)
时)
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.getpreferredencoding()
'ANSI_X3.4-1968'
>>> import sys
>>> sys.getfilesystemencoding()
'ascii'
>>>
和locale
命令打印:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE=en_HK.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
答案 0 :(得分:2)
我有类似的问题。对我来说,最初没有设置环境变量LANG
(您可以通过运行env
进行检查)
$ python3 -c 'import locale; print(locale.getdefaultlocale())'
(None, None)
$ python3 -c 'import locale; print(locale.getpreferredencoding())'
ANSI_X3.4-1968
对我而言,可用的语言环境是(在新的Ubuntu 18.04 Docker映像上):
$ locale -a
C
C.UTF-8
POSIX
所以我选择了utf-8:
$ export LANG="C.UTF-8"
然后一切正常
$ python3 -c 'import locale; print(locale.getdefaultlocale())'
('en_US', 'UTF-8')
$ python3 -c 'import locale; print(locale.getpreferredencoding())'
UTF-8
如果您选择了一个不可用的语言环境,例如
export LANG="en_US.UTF-8"
它将不起作用:
$ python3 -c 'import locale; print(locale.getdefaultlocale())'
('en_US', 'UTF-8')
$ python3 -c 'import locale; print(locale.getpreferredencoding())'
ANSI_X3.4-1968
这就是locale
给出错误消息的原因:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
答案 1 :(得分:0)
我通过运行以下命令解决了该问题:
apt install locales-all
答案 2 :(得分:-2)
我认为您误读了错误消息。小心区分 Unicode De codeError 和 Unicode En codeError 。
你说Python抱怨“ascii编解码器无法解码某些字符”。但是,据我所知,没有这样的错误信息。比较以下两种情况:
>>> b = 'é'.encode('utf8')
>>> b.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can’t decode byte 0xc3 in position 0: ordinal not in range(128)
>>> 'é'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can’t encode character '\xe9' in position 0: ordinal not in range(128)
要么“不能解码字节”或“不能编码字符”,但它永远不会“无法解码字符”。
这可能看起来很迂腐,但在这一行中,
for line in f: print(line)
您有 de 编码(冒号前)和 en 编码(print
表达式)。因此,您需要确定哪个进程导致了问题。一种可能性是将其写成两行。
但是,如果f
在您编写时使用encoding='utf-8'
打开,那么我很确定问题是由print
表达式引起的。
默认情况下,print()
会写入sys.stdout
。由于此流在启动Python时已经打开,因此其编码也已设置 - 具体取决于您的环境。由于在您的语言环境中未设置LC_ALL
,因此使用ASCII默认值(“ANSI X3.4-1968”)(这可能会在标题中回答您的问题)。
如果您不能或不想更改区域设置,可以执行以下操作:将Python中的UTF-8文本发送到STDOUT:
使用基础二进制流:
for line in f:
sys.stdout.buffer.write(line.encode('utf-8')
重新编码sys.stdout
(实际上:使用重新编码的版本替换 sys.stdout
):
import codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer)
在任何情况下,您的终端仍然无法正确显示UTF-8文本,因为它无法正常显示,或者因为没有配置这样做。在这种情况下,你可能会看到问号或mojibake。但这是一个不同的故事,超出了Python的控制......