关于python:UnicodeDecodeError:’ascii’编解码器无法解码位置1的字节0xef

UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 1

我在尝试将字符串编码为UTF-8时遇到了一些问题。我尝试过很多方法,包括使用string.encode('utf-8')unicode(string),但我得到了错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 1: ordinal not in range(128)

这是我的字符串:

1
(??ω??)?

我不知道怎么回事,知道吗?

编辑:问题是打印的字符串显示不正确。另外,当我尝试转换它时出现此错误:

1
2
3
4
5
6
7
8
9
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type"help","copyright","credits" or"license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)


这是因为终端的编码没有设置为UTF-8。这是我的终点站

1
2
3
4
5
6
7
8
9
10
11
$ echo $LANG
en_GB.UTF-8
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59)
[GCC 4.6.3] on linux2
Type"help","copyright","credits" or"license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(??ω??)?
>>>

在我的终端上,该示例与上面的示例一起工作,但是如果我去掉了LANG设置,那么它将不工作。

1
2
3
4
5
6
7
8
9
10
11
12
$ unset LANG
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59)
[GCC 4.6.3] on linux2
Type"help","copyright","credits" or"license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)
>>>

请查阅Linux变体的文档,以了解如何使此更改永久化。


尝试:

1
2
string.decode('utf-8')  # or:
unicode(string, 'utf-8')

编辑:

'(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'.decode('utf-8')u'(\uff61\uff65\u03c9\uff65\uff61)\uff89'是正确的。

所以你的问题一定是在某个地方,可能如果你试图用它做些什么,如果有一个隐式的转换正在进行(可能是打印,写入流…)

要说更多,我们需要看一些代码。


我在https://stackoverflow.com/a/10561979/1346705上对mata的评论和尼克·克雷格·伍德的演示进行了+1。您已正确解码字符串。问题出在print命令上,因为它将unicode字符串转换为控制台编码,而控制台无法显示该字符串。尝试将字符串写入文件,并使用支持Unicode的合适编辑器查看结果:

1
2
3
4
5
6
7
import codecs

s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
s1 = s.decode('utf-8')
f = codecs.open('out.txt', 'w', encoding='utf-8')
f.write(s1)
f.close()

然后你会看到(??ω??)?


如果您在远程主机上工作,请查看本地PC上的/etc/ssh/ssh_config

当此文件包含一行时:

1
SendEnv LANG LC_*

在行首添加#进行注释。也许有帮助。

通过这一行,ssh将与语言相关的PC环境变量发送到远程主机。这会引起很多问题。


尝试在脚本开始时将系统默认编码设置为utf-8,以便使用该设置对所有字符串进行编码。

1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


我的终端没有问题。上面的回答帮助我找到了正确的方向,但直到我加上'ignore'后才对我起作用:

1
fix_encoding = lambda s: s.decode('utf8', 'ignore')

如下面的注释所示,这可能会导致不期望的结果。奥思,它也可能只是做得足够好,使事情工作,你不在乎失去一些字符。


按照安德烈·克拉萨斯基的建议,可以在脚本顶部使用下面的代码。

1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

但我建议您在脚本的最上面添加# -*- coding: utf-8 -*行。

在我尝试执行basic.py时,省略它会导致下面的错误。

1
2
3
$ python basic.py
  File"01_basic.py", line 14
SyntaxError: Non-ASCII character '\xd9' in file basic.py on line 14, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

下面是basic.py中的代码,它抛出了上述错误。

错误代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('?? ???????')):
        doc.append('??? ?????? ?????? ????? ??? ?????')
        doc.append(italic('????? ???????? ??? ???? ????'))

        with doc.create(Subsection('??? ???????????')):
            doc.append('?????? ????? ??????????: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

然后,我在最上面加上了# -*- coding: utf-8 -*-行并执行。它奏效了。

代码无错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding: utf-8 -*-
from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('?? ???????')):
        doc.append('??? ?????? ?????? ????? ??? ?????')
        doc.append(italic('????? ???????? ??? ???? ????'))

        with doc.create(Subsection('??? ???????????')):
            doc.append('?????? ????? ??????????: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

谢谢。


看起来您的字符串是编码到utf-8的,那么问题到底是什么?或者你想在这里做什么?

1
2
3
4
5
6
7
8
9
10
11
12
Python 2.7.3 (default, Apr 20 2012, 22:39:59)
[GCC 4.6.3] on linux2
Type"help","copyright","credits" or"license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(??ω??)?
>>> s2 = u'(??ω??)?'
>>> s2 == s1
True
>>> s2
u'(\uff61\uff65\u03c9\uff65\uff61)\uff89'


在我的例子中,这是由我的Unicode文件与"bom"一起保存造成的。为了解决这个问题,我使用bbedit打开了文件,并选择了"另存为…"来编码"unicode(utf-8)",而不是"unicode(utf-8,with bom)"。


这适用于Ubuntu 15.10:

1
2
sudo locale-gen"en_US.UTF-8"
sudo dpkg-reconfigure locales

我得到了同样类型的错误,我发现控制台不能用另一种语言显示字符串。因此,我对下面的代码进行了更改,将默认字符集设置为utf-8。

1
2
3
data_head = [('\x81\xa1\x8fo\x89\xef\x82\xa2\x95\xdb\x8f\xd8\x90\xa7\x93x\x81\xcb3\x8c\x8e\x8cp\x91\xb1\x92\x86(\x81\x86\x81\xde\x81\x85)\x81\xa1\x8f\x89\x89\xf1\x88\xc8\x8aO\x81A\x82\xa8\x8b\xe0\x82\xcc\x90S\x94z\x82\xcd\x88\xea\x90\xd8\x95s\x97v\x81\xa1\x83}\x83b\x83v\x82\xcc\x82\xa8\x8e\x8e\x82\xb5\x95\xdb\x8c\xaf\x82\xc5\x8fo\x89\xef\x82\xa2\x8am\x92\xe8\x81\xa1', 'shift_jis')]
default_charset = 'UTF-8' #can also try 'ascii' or other unicode type
print ''.join([ unicode(lin[0], lin[1] or default_charset) for lin in data_head ])


bom,我经常看到bom

vi文件,使用

1
:set nobomb

并保存它。在我的情况下几乎总是能解决的


我也有同样的错误,URL包含非ASCII字符(值大于128的字节)

1
url = url.decode('utf8').encode('utf-8')

在python 2.7中,我认为这个分配改变了str内部表示中的"某物"——也就是说,它强制正确解码url中的备份字节序列,最后将字符串放入一个utf-8 str,所有的魔力都在正确的位置。Python中的Unicode对我来说是黑色的魔法。希望有用


这是最好的答案:https://stackoverflow.com/a/4027726/2159089

在Linux中:

1
export PYTHONIOENCODING=utf-8

所以sys.stdout.encoding是可以的。


我用'engine':'django.db.backends.mysql'解决了文件settings.py中的更改问题,不使用'engine':'mysql.connector.django',


只需使用str()将文本显式转换为字符串即可。为我工作。