问题是该错误并不总是可重现的。它有时可以在某些页面上使用,有时它会通过抛出
UnicodeEncodeError
来阻塞。我已经尝试了几乎所有我能想到的东西,但没有找到任何能够正常工作而又不会引发某种与Unicode相关的错误的方法。引起问题的代码部分之一是如下所示:
agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
下面是运行上述代码段时在某些字符串上产生的堆栈跟踪:
Traceback (most recent call last):
File "foobar.py", line 792, in <module>
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
我怀疑这是因为某些页面(或更具体地说,来自某些站点的页面)可能已编码,而其他页面可能未编码。所有站点都位于英国,并提供供英国消费的数据-因此,与英语以外的其他任何形式的内部化或文字处理有关的问题都没有。
任何人对如何解决这个问题,以便我可以始终如一地解决此问题?
#1 楼
您需要阅读Python Unicode HOWTO。此错误是第一个示例。基本上,停止使用
str
将unicode转换为编码的文本/字节。相反,请正确使用
.encode()
编码字符串:p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
或完全使用unicode进行工作。
评论
同意!我受教的一个很好的经验法则是使用“ unicode三明治”的想法。您的脚本接受外界的字节,但所有处理均应以unicode进行。仅当准备好输出数据时,才应将其重新划分为字节!
– Andbdrew
2012年3月30日12:29
如果有人对此感到困惑,我会发现一个奇怪的事情:我的终端使用utf-8,并且当我打印utf-8字符串时,它可以很好地工作。但是,当我将程序输出通过管道传输到文件时,它将引发UnicodeEncodeError。实际上,当输出重定向到文件或管道时,我发现sys.stdout.encoding为None!解决.encode('utf-8')解决了这个问题。
– drevicko
2012-12-18 18:15
@drevicko:改用PYTHONIOENCODING = utf-8,即打印Unicode字符串,并让环境设置所需的编码。
– jfs
2013年12月21日,下午3:51
@steinar:在每种情况下都没有有效的方法。通常,用户不必关心您使用Python来实现实用程序(如果出于某种原因决定用另一种语言重新实现该接口,则该接口不应更改),因此,您不应期望该用户甚至知道python-特定的环境。强制用户指定字符编码是不良的UI;如有必要,将字符编码嵌入报告格式。注意:一般情况下,硬编码编码不能是“明智的默认选择”。
– jfs
2015年11月25日10:24
这是糟糕而令人困惑的建议。人们使用str的原因是因为对象还不是字符串,所以没有要调用的.encode()方法。
–塞林
16-10-5在17:59
#2 楼
这是经典的python unicode痛点!考虑以下内容:到目前为止,一切都很好,但是如果我们调用str(a),让我们看看会发生什么:a = u'bats\u00E0'
print a
=> batsà
天哪,这对任何人都没有好处!要解决该错误,请使用.encode明确编码字节,并告诉python使用哪种编解码器:
voil \ u00E0!
问题是,当您调用str()时,python使用默认的字符编码来尝试对给定的字节进行编码,在您的情况下,有时表示为unicode字符。要解决此问题,您必须告诉python如何使用.encode('whatever_unicode')处理您给它的字符串。大多数情况下,使用utf-8应该会很好。
有关此主题的出色论述,请参阅Ned Batchelder在PyCon上的演讲:http://nedbatchelder.com/text/unipain.html
评论
个人说明:尝试键入“ .encode”时,请不要意外键入“ .unicode”,然后请问为什么没有任何效果。
–跳过霍夫曼
2012年12月24日14:38
好建议。但是,当您使用str(x)打印可能是或不是字符串的对象时,您会怎么做呢?如果x是数字,日期时间,布尔值或普通字符串,则str(x)有效。突然,如果它是一个unicode,它将停止工作。有没有一种方法可以实现相同的行为,或者我们现在是否需要添加IF检查以测试对象是否为使用.encode的字符串,否则是否使用str()?
– Dirk R
18年1月25日在16:50
可以使用“无”值询问相同的问题。
–Vadorequest
18-11-19在13:54
#3 楼
我发现可以用优雅的方法删除符号并继续将字符串保留为字符串,如下所示:yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')
请务必注意,使用ignore选项很危险,因为它从使用它的代码中无声地删除任何unicode(和国际化)支持,如此处所示(转换unicode):
>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
评论
你让我今天一整天都感觉很好!对于utf-8,只需执行以下操作:yourstring = yourstring.encode('utf-8','ignore')。decode('utf-8')
–luca76
17年2月14日在15:38
对我来说,这确实有效,但是我的情况有所不同,我正在保存文件名,并且名称中带有“ /”,并且路径不存在,所以我必须使用.replace(“ /”,“”)并保存我的脚本。同时忽略ASCII也适用于'utf-8'情况。
– Akash Kandpal
18年7月5日在8:38
@ harrypotter0使用os.path.join()正确连接文件路径,当您开始进行跨平台编程时,这是一个很好的习惯。 :)
–login_not_failed
18年8月22日在7:36
#4 楼
好吧,我尝试了所有内容,但没有帮助,在谷歌搜索后发现以下内容并有所帮助。正在使用python 2.7。
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
评论
不要这样stackoverflow.com/questions/3828723/…,尽管当您在搜索错误时在结果顶部附近有类似stackoverflow.com/a/31137935/2141635的答案时,我可以理解为什么它似乎是一个好主意。
–坎宁安(Padraic Cunningham)
16 Sep 8'在11:50
我尝试了该主题中的几乎所有建议,但实际上没有一个对我有用。最后我尝试了这个。实际上,这是唯一一种既简单又好用的方法。如果有人说“不要这样做,那么请提供一个简单的解决方案。否则请使用此解决方案。因为这是一个很好的工作副本和过去的解决方案。
–Richard de Ree
17年8月24日在11:48
如何在python3中完成?很高兴知道。
–卡纳尔瓦·彼得(Kanerva Peter)
18 Mar 7 '18 at 12:24
经过如此多的挫败之后,这个工作了。谢谢你
–阿夫拉罕·卓巴
18年6月17日在21:47
我只添加if sys.version_info.major <3:
–法尔肯教授
18年7月15日在13:52
#5 楼
导致甚至打印失败的一个细微问题是环境变量设置错误,例如。此处LC_ALL设置为“ C”。在Debian中,他们不鼓励设置它:Locale上的Debian Wiki$ echo $LANG
en_US.utf8
$ echo $LC_ALL
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà
评论
遇到了完全相同的问题,很遗憾,我没有在报告之前对其进行检查。非常感谢。顺便说一句,您可以用env | grep -E'(LC | LANG)'替换前两个命令。
–德米特里(Dmitry Verhoturov)
15年8月8日在7:28
对于错误的编码问题,只有我的两分钱。我经常在“ subshell模式”(Ctrl-O)中使用mc,而且我也忘记了向bash添加以下别名:alias mc =“ LANG = en_EN.UTF-8 mc”。因此,当我尝试内部运行依赖ru_RU.UTF-8编写的脚本时,它们会死掉。在我发现真正的问题之前,尝试了该线程的很多东西。 :)
–login_not_failed
18年8月22日在7:52
你太棒了。在GSUTIL中,正是由于这个问题,我的rsync失败了。修复了LC_ALL,一切都可以像红酒一样工作。 <3谢谢<3
– dsignr
19/12/23在5:24
#6 楼
问题是您正在尝试打印unicode字符,但是您的终端不支持该字符。您可以尝试安装
language-pack-en
软件包来修复此问题:sudo apt-get install language-pack-en
,它为所有受支持的软件包(包括Python)提供英语翻译数据更新。如有必要,请安装其他语言包(取决于您要打印的字符)。
在某些Linux发行版中,需要确保正确设置默认的英语语言环境(因此unicode)字符可以由外壳/终端处理)。有时安装它比手动配置要容易。
然后在编写代码时,请确保在代码中使用正确的编码。
例如:
open(foo, encoding='utf-8')
如果仍然有问题,请仔细检查系统配置,例如:
您的语言环境文件(
/etc/default/locale
),应具有例如LANG="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
或:
LC_ALL=C.UTF-8
LANG=C.UTF-8
LANG
/ LC_CTYPE
的值在外壳程序中。通过以下方法检查外壳程序支持的语言环境:
locale -a | grep "UTF-8"
演示该问题和解决方案新鲜的VM。
初始化和配置VM(例如,使用
vagrant
):vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
请参阅:可用Ubuntu盒..
打印unicode字符(例如
™
之类的商标符号):$ python -c 'print(u"\u2122");'
Traceback (most recent call last):
File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
现在安装
language-pack-en
:$ sudo apt-get -y install language-pack-en
The following extra packages will be installed:
language-pack-en-base
Generating locales...
en_GB.UTF-8... /usr/sbin/locale-gen: done
Generation complete.
现在问题应该是解决:
$ python -c 'print(u"\u2122");'
™
否则,请尝试以下命令:
$ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
™
评论
language-pack-en与Python或这个问题有什么关系? AFAIK,它可以为消息提供语言翻译,但与编码无关
–阿拉斯泰尔·麦考马克(Alastair McCormack)
15/12/26在10:47
在某些Linux发行版中,需要确保正确设置了默认的英语语言环境,尤其是在终端上运行Python脚本时。它对我有用。另请:字符编码
– Kenorb
15年12月26日在11:00
喔好吧。您的意思是是否要使用非英语语言环境?我猜用户还必须编辑/etc/locale.gen以确保在使用之前已建立他们的语言环境?
–阿拉斯泰尔·麦考马克(Alastair McCormack)
15/12/26在11:04
@AlastairMcCormack从/ etc / default / locale(因为/etc/locale.gen不存在)中注释了LANG并运行了locale-gen,但是它没有帮助。我不确定使用哪种语言打包,因为我找不到太多的文档,列出其中的内容也无济于事。
– Kenorb
15/12/27在13:07
台式机系统上不太可能已经没有utf-8语言环境,即,您可能不需要安装任何内容,只需配置LANG / LC_CTYPE / LC_ALL(例如,LANG = C.UTF-8) 。
– jfs
16-1-1的3:10
#7 楼
对我来说,有效的方法是:BeautifulSoup(html_text,from_encoding="utf-8")
希望对别人有帮助。
#8 楼
实际上,我发现在大多数情况下,只需删除那些字符就容易得多:s = mystring.decode('ascii', 'ignore')
评论
“完全”通常不是它所执行的。它丢弃了您应该弄清楚如何正确处理的东西。
–tripleee
2014年12月13日下午16:53
仅仅去除“那些”(非英语)字符不是解决方案,因为python必须支持所有语言,您不认为吗?
– alemol
2015年1月9日在19:47
不赞成投票。这根本不是正确的解决方案。了解如何使用Unicode:joelonsoftware.com/articles/Unicode.html
–安德鲁·费里尔(Andrew Ferrier)
15年1月13日在13:04
看,给出此特定答案的最明智的方式是这样的:认识到ascii赋予了某些语言和用户一定的特权-这是逃生舱口,可能会被那些利用粗略的第一步通过的用户所利用。 ,脚本一起执行潜在的工作,以实现完整的unicode支持。
–哈哈
16年6月19日在14:07
如果我编写的脚本只需要在内部公司应用程序中将英文文本输出到stdout,我就是想解决这个问题。无论如何。
– kagronick
17年5月11日下午14:11
#9 楼
在shell中:通过以下命令查找受支持的UTF-8语言环境:
locale -a | grep "UTF-8"
在运行脚本之前将其导出,例如:
export LC_ALL=$(locale -a | grep UTF-8)
,或手动像这样:
export LC_ALL=C.UTF-8
通过打印特殊字符进行测试,例如
™
:python -c 'print(u"\u2122");'
在Ubuntu中经过测试。
评论
是的,这是最好的简短答案,我们无法修改源代码以使用.encode
– Neo.Mxn0
1月19日18:17
设置LC_ALL后,我在python3中使用了它,现在可以正常工作。谢谢
–阿贾伊
7月18日14:03
#10 楼
这是其他一些所谓的“警惕”答案的重新表述。在某些情况下,尽管这里有人提出抗议,但简单地扔掉麻烦的字符/字符串是一个好的解决方案。def safeStr(obj):
try: return str(obj)
except UnicodeEncodeError:
return obj.encode('ascii', 'ignore').decode('ascii')
except: return ""
测试它:
if __name__ == '__main__':
print safeStr( 1 )
print safeStr( "test" )
print u'98\xb0'
print safeStr( u'98\xb0' )
结果:
1
test
98°
98
更新:我最初的答案是为Python 2编写的。对于Python 3:
def safeStr(obj):
try: return str(obj).encode('ascii', 'ignore').decode('ascii')
except: return ""
注意:如果您希望将
?
指示符留在“不安全” Unicode字符所在的位置,请在调用中指定replace
而不是ignore
来为错误处理程序编码。建议:您可能想将此函数命名为
toAscii
?最后,这是一个优先问题... 最后,这是一个使用
six
的更强大的PY2 / 3版本,在这里我选择使用replace
,并加入一些字符交换来替换花哨的unicode引号和向左或向右卷曲的撇号与作为ascii集一部分的简单垂直对象。您可以自己进行此类互换:from six import PY2, iteritems
CHAR_SWAP = { u'\u201c': u'"'
, u'\u201D': u'"'
, u'\u2018': u"'"
, u'\u2019': u"'"
}
def toAscii( text ) :
try:
for k,v in iteritems( CHAR_SWAP ):
text = text.replace(k,v)
except: pass
try: return str( text ) if PY2 else bytes( text, 'replace' ).decode('ascii')
except UnicodeEncodeError:
return text.encode('ascii', 'replace').decode('ascii')
except: return ""
if __name__ == '__main__':
print( toAscii( u'testin\u2019' ) )
#11 楼
在脚本开头(或第二行)下方添加以下行:# -*- coding: utf-8 -*-
这是python源代码编码的定义。 PEP 263中的更多信息。
评论
从外部文件加载的处理后的文本包含utf-8编码时,这不能解决问题。这仅对使用给定python脚本本身编写的文字有所帮助,只是python解释器的线索,但对文本处理没有影响。
– Mikaelblomkvistsson
19年1月8日在14:43
#12 楼
我总是将以下代码放在python文件的前两行中:# -*- coding: utf-8 -*-
from __future__ import unicode_literals
#13 楼
在此处找到简单的帮助程序功能。def safe_unicode(obj, *args):
""" return the unicode representation of obj """
try:
return unicode(obj, *args)
except UnicodeDecodeError:
# obj is byte string
ascii_text = str(obj).encode('string_escape')
return unicode(ascii_text)
def safe_str(obj):
""" return the byte string representation of obj """
try:
return str(obj)
except UnicodeEncodeError:
# obj is unicode
return unicode(obj).encode('unicode_escape')
评论
要获取转义的字节串(使用ascii编码将任意Unicode字符串转换为字节),可以使用反斜杠替换错误处理程序:u'\ xa0'.encode('ascii','backslashreplace')。尽管您应该避免这种表示形式,而是将环境配置为接受非ASCII字符-现在是2016年!
– jfs
16年1月1日,下午3:05
新年快乐@ J.F。Sebastian。我只是对Python-Unicode问题感到沮丧,然后终于得到了有效的解决方案。我对此一无所知。无论如何,感谢小费。
–巴拉格·泰吉(Parag Tyagi)
16年1月1日,下午6:53
#14 楼
只需添加到变量encode('utf-8')agent_contact.encode('utf-8')
#15 楼
this这至少在Python 3中有效...Python 3
有时错误在于环境变量中,因此
import os
import locale
os.environ["PYTHONIOENCODING"] = "utf-8"
myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8")
...
print(myText.encode('utf-8', errors='ignore'))
编码中的错误将被忽略。
#16 楼
我只是使用以下代码:import unicodedata
message = unicodedata.normalize("NFKD", message)
检查有关它的文档说明:
unicodedata.normalize(form,unistr)返回
Unicode字符串unistr的普通形式。格式的有效值为'NFC','NFKC',
'NFD'和'NFKD'。
Unicode标准定义了Unicode
字符串的各种规范化形式,基于规范对等和相容性对等的定义。在Unicode中,可以以多种方式
表示几个字符。例如,字符U + 00C7(带有CEDILLA的拉丁文大写字母C)也可以表示为序列
U + 0043(拉丁文的大写字母C)U + 0327(合并CEDILLA)。 />
每个字符都有两种规范形式:规范形式C和
规范形式D。规范形式D(NFD)也称为规范分解,将每个字符转换为
普通形式C(NFC)首先应用规范分解,然后
再次组成预组合字符。
除了这两种形式外,还有两种形式基于兼容性等效性的其他范式
。在Unicode中,支持某些字符,通常将与其他字符统一。例如,U + 2160(罗马数字ONE)与U + 0049
(拉丁大写字母I)实际上是同一回事。但是,Unicode支持它与现有字符集(例如gb2312)兼容。
常规形式KD(NFKD)将应用兼容性分解,
即替换所有兼容字符及其等效字符。
正规形式KC(NFKC)首先应用兼容性分解,
然后是规范组成。
即使两个unicode字符串均被标准化并且看起来与a相同/>人类的读者,如果一个具有组合字符而另一个没有,
他们可能不相等。
为我解决。简单容易。
#17 楼
请打开终端并执行以下命令:export LC_ALL="en_US.UTF-8"
#18 楼
下面的解决方案为我工作,只需在我的字符串之前添加u“ String”
(将字符串表示为unicode)。
result_html = result.to_html(col_space=1, index=False, justify={'right'})
text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report. Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)
#19 楼
我只是遇到了这个问题,而Google带领我来到这里,因此,在这里添加一些通用的解决方案对我来说就是这样:# 'value' contains the problematic data
unic = u''
unic += value
value = unic
我有这个想法在阅读了Ned的演示文稿之后。
但是,我并没有声称完全理解它的工作原理。因此,如果有人可以编辑此答案或发表评论以进行解释,我将不胜感激。
评论
什么是价值类型?之前和之后?我认为这样做的原因是,通过执行与unic = unic +值相同的unic + =值,您要添加一个字符串和一个unicode,其中python然后假定生成的unic的unicode即更精确的类型(考虑一下当您执行此操作时,a = float(1)+ int(1),a变为float),然后value = unic将value指向碰巧是unicode的新unic对象。
–汤姆·迈德汀(Tom Myddeltyn)
16年5月24日在21:16
#20 楼
我们在Django中使用本地化的固定装置运行manage.py migrate
时遇到了此错误。 问题很简单,就是Django容器(我们使用docker)缺少
# -*- coding: utf-8 -*-
env变量。将
/etc/default/locale
设置为LANG
并重新启动容器,然后重新运行迁移即可解决此问题。 br />#21 楼
这里的许多答案(例如@agf和@Andbdrew)已经解决了OP问题的最直接方面。但是,我认为有一个微妙但重要的方面已被很大程度上忽略,并且对于像我这样的每个人来说,在尝试理解Python的编码意义时最终都遇到了非常重要的问题:字符表示的Python 2与Python 3管理大不相同。我觉得很多困惑与人们在不了解版本的情况下阅读Python编码有关。
我建议有兴趣了解OP问题根本原因的人首先阅读Spolsky对字符表示法和Unicode的介绍,然后转到Python 2和Python 3中的Unicode Batchelder。
评论
是的,我的错误是在python 2.7上,'a'.format(u'ñ'),正确的解决方案是不使用.encode('utf-8')而是始终使用unicode字符串,(python 3中的默认值) ):u'a'.format(u'ñ'),
– RogelioTriviño
19年11月19日在13:16
#22 楼
尽量避免将变量转换为str(variable)。有时,可能会引起问题。避免简单的技巧:
try:
data=str(data)
except:
data = data #Don't convert to String
上面的示例也将解决Encode错误。
评论
这是行不通的,因为您只会遇到例外中的错误
–奥雷·科琳(Aurele Collinet)
19-10-8在10:04
#23 楼
推荐的解决方案对我不起作用,我可以忍受所有非ascii字符的转储,因此s = s.encode('ascii',errors='ignore')
这使我留下了一些不会被抛出错误的东西。
#24 楼
一般情况下,将此不受支持的编码字符串(例如data_that_causes_this_error
)写入某个文件(例如results.txt
),可以正常工作f = open("results.txt", "w")
f.write(data_that_causes_this_error.encode('utf-8'))
f.close()
#25 楼
如果您有类似packet_data = "This is data"
的内容,请在初始化packet_data
之后在下一行执行此操作:unic = u''
packet_data = unic
#26 楼
python 3.0及更高版本的更新。在python编辑器中尝试以下操作:locale-gen en_US.UTF-8
export LANG=en_US.UTF-8 LANGUAGE=en_US.en
LC_ALL=en_US.UTF-8
这会将系统的默认语言环境编码设置为UTF-8格式。
更多可以在PEP 538上阅读-将旧版C语言环境强制为基于UTF-8的语言环境。
#27 楼
我在尝试将Unicode字符输出到stdout
时遇到了这个问题,但使用sys.stdout.write
而不是打印(以便我也可以支持将输出输出到其他文件)。从BeautifulSoup自己的文档中,我解决了这个问题与编解码器库一起:
import sys
import codecs
def main(fIn, fOut):
soup = BeautifulSoup(fIn)
# Do processing, with data including non-ASCII characters
fOut.write(unicode(soup))
if __name__ == '__main__':
with (sys.stdin) as fIn: # Don't think we need codecs.getreader here
with codecs.getwriter('utf-8')(sys.stdout) as fOut:
main(fIn, fOut)
#28 楼
当使用Apache部署django项目时,经常会发生此问题。因为Apache在/ etc / sysconfig / httpd中设置环境变量LANG = C。只需打开文件并注释(或更改为您的样式)此设置即可。或使用WSGIDaemonProcess命令的lang选项,在这种情况下,您将能够将不同的LANG环境变量设置为不同的虚拟主机。#29 楼
这将起作用: >>>print(unicodedata.normalize('NFD', re.sub("[\(\[].*?[\)\]]", "", "bats\xc3\xa0")).encode('ascii', 'ignore'))
输出:
>>>bats
评论
如果您以用户而非开发人员的身份遇到这些错误,请检查serverfault.com/questions/54591/…和askubuntu.com/questions/599808/…我要补充一点,不要将onlinegdb.com/online_python_interpreter用于此内容。正在使用该解释器试用内容,并且未正确配置Unicode!总是以'B'\ nnn''格式打印...当我想要的只是guillemet时!在VM上试用过,它可以使用chr()立即按预期工作
试试这个import os;导入区域设置; os.environ [“ PYTHONIOENCODING”] =“ utf-8”; myLocale = locale.setlocale(category = locale.LC_ALL,locale =“ zh_CN.UTF-8”); ... print(myText.encode('utf-8',errors ='ignore')))。
@hhh我运行了您的代码段NameError:未定义名称'myText'
在执行脚本之前,尝试在外壳中设置PYTHONIOENCODING:$ export PYTHONIOENCODING = utf8