UnicodeEncodeError:'ascii' 编解码器无法对位置 20 处的字符 u'\xa0' 进行编码:序数不在范围内(128)
- 2024-11-20 08:44:00
- admin 原创
- 7
问题描述:
我在处理从不同网页(不同网站)获取的文本中的 unicode 字符时遇到了问题。我正在使用 BeautifulSoup。
问题是错误并不总是可重现的;它有时适用于某些页面,有时,它会抛出一个错误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工作。
解决方案 2:
这是典型的 Python unicode 痛点!考虑以下几点:
a = u'bats/u00E0'
print a
=> batsà
到目前为止一切都很好,但如果我们调用 str(a),让我们看看会发生什么:
str(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)
哦,这可不会给任何人带来任何好处!要修复此错误,请使用 .encode 明确编码字节,并告诉 python 要使用哪种编解码器:
a.encode('utf-8')
=> 'batsxc3xa0'
print a.encode('utf-8')
=> batsà
瞧!
问题是,当您调用 str() 时,python 使用默认字符编码来尝试编码您提供的字节,在您的情况下,这些字节有时是 unicode 字符的表示。要解决此问题,您必须使用 .encode('whatever_unicode') 告诉 python 如何处理您提供的字符串。大多数情况下,使用 utf-8 应该没问题。
有关该主题的出色阐述,请参阅 Ned Batchelder 的 PyCon 演讲:http: //nedbatchelder.com/text/unipain.html
解决方案 3:
我发现了一个优雅的解决方法,可以删除符号并继续将字符串保留为字符串,如下所示:
yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')
值得注意的是,使用 ignore 选项是危险的,因为它会默默地从使用它的代码中删除任何 unicode(和国际化)支持,如下所示(转换 unicode):
>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
解决方案 4:
好吧,我尝试了所有方法但没有帮助,在谷歌搜索之后,我发现了以下内容并且有所帮助。正在使用 python 2.7。
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
解决方案 5:
导致打印失败的一个细微问题是环境变量设置错误,例如,此处 LC_ALL 设置为“C”。在 Debian 中,他们不鼓励设置它:Debian wiki 上的 Locale
$ 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à
解决方案 6:
问题是您正在尝试打印一个 unicode 字符,但是您的终端不支持它。
您可以尝试安装language-pack-en
包来修复该问题:
sudo apt-get install language-pack-en
它为所有受支持的软件包(包括 Python)提供英语翻译数据更新。如有必要,请安装不同的语言包(取决于您要打印的字符)。
在某些 Linux 发行版中,需要安装它以确保默认英语区域设置正确设置(以便 shell/终端可以处理 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
。通过以下方式检查你的 shell 支持哪个语言环境:
locale -a | grep "UTF-8"
在全新 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");'
™
解决方案 7:
在 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 中测试。
解决方案 8:
事实上我发现在大多数情况下,删除这些字符要简单得多:
s = mystring.decode('ascii', 'ignore')
解决方案 9:
对我来说,有效的方法是:
BeautifulSoup(html_text,from_encoding="utf-8")
希望这对某人有帮助。
解决方案 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'98xb0'
print safeStr( u'98xb0' )
结果:
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
改用其他名称来命名此函数?这只是个人喜好问题...
最后,这是一个使用 的更强大的 PY2/3 版本six
,其中我选择使用replace
,并加入一些字符交换,以使用简单的垂直字符(ascii 集的一部分)替换向左或向右卷曲的花哨 unicode 引号和撇号。您可以自己扩展此类交换:
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。
解决方案 12:
我总是将下面的代码放在 python 文件的前两行:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
解决方案 13:
它对我有用:
export LC_CTYPE="en_US.UTF-8"
解决方案 14:
唉,这至少在 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'))
在编码过程中,错误会被忽略。
解决方案 15:
如果是打印语句的问题,很多时候只是终端打印的问题。这对我有帮助:export PYTHONIOENCODING=UTF-8
解决方案 16:
简单的辅助函数可以在这里找到。
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')
解决方案 17:
只需添加到变量编码('utf-8')
agent_contact.encode('utf-8')
解决方案 18:
请打开终端并执行以下命令:
export LC_ALL="en_US.UTF-8"
解决方案 19:
回答晚了,但这个错误与你的终端编码不支持某些字符有关。
我python3
使用以下方法修复了它:
import sys
import io
sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
print("é, à, ...")
解决方案 20:
我刚刚使用了以下内容:
import unicodedata
message = unicodedata.normalize("NFKD", message)
检查一下文档中关于它的内容:
unicodedata.normalize(form, unistr) 返回 Unicode 字符串 unistr 的正常形式 form。form 的有效值为“NFC”、“NFKC”、“NFD”和“NFKD”。
Unicode 标准根据规范等价性和兼容性等价性定义,定义了 Unicode 字符串的各种规范化形式。在 Unicode 中,多个字符可以用各种方式表示。例如,字符 U+00C7(带下划线的拉丁大写字母 C)也可以表示为序列 U+0043(带下划线的拉丁大写字母 C)U+0327(组合下划线)。
对于每个字符,有两种范式:范式 C 和范式 D。范式 D (NFD) 也称为规范分解,将每个字符转换为其分解形式。范式 C (NFC) 首先应用规范分解,然后再次组合预先组合的字符。
除了这两种形式外,还有两种基于兼容性等价性的附加范式。Unicode 支持某些字符,这些字符通常会与其他字符统一。例如,U+2160(罗马数字 1)实际上与 U+0049(拉丁大写字母 I)相同。但是,Unicode 支持它以兼容现有字符集(例如 gb2312)。
范式 KD (NFKD) 将应用兼容性分解,即用等价字符替换所有兼容性字符。范式 KC (NFKC) 首先应用兼容性分解,然后应用规范组合。
即使两个 Unicode 字符串经过规范化,对人类读者来说看起来相同,但如果其中一个具有组合字符而另一个没有,则它们可能无法进行比较。
帮我解决了。简单又容易。
解决方案 21:
下面的解决方案对我有用,刚刚添加
u “字符串”
(将字符串表示为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)
解决方案 22:
推荐的解决方案对我来说不起作用,我可以忍受转储所有非 ascii 字符,所以
s = s.encode('ascii',errors='ignore')
这让我得到了一些不会引发错误的东西。
解决方案 23:
在将不受支持的编码 字符串(比如说data_that_causes_this_error
)写入某个文件(例如)的一般情况下results.txt
,这是可行的
f = open("results.txt", "w")
f.write(data_that_causes_this_error.encode('utf-8'))
f.close()
解决方案 24:
我刚刚遇到了这个问题,然后谷歌引导我到了这里,所以只是为了补充这里的一般解决方案,这是对我有用的:
# 'value' contains the problematic data
unic = u''
unic += value
value = unic
在阅读了Ned 的演讲后我有了这个想法。
不过,我并不声称完全理解为什么这样做有效。因此,如果有人可以编辑此答案或发表评论进行解释,我将不胜感激。
解决方案 25:
manage.py migrate
我们在使用本地化装置在 Django 中运行时遇到了这个错误。
我们的源包含# -*- coding: utf-8 -*-
声明,MySQL 已正确配置为 utf8,并且 Ubuntu 具有适当的语言包和值/etc/default/locale
。
问题很简单,Django 容器(我们使用 docker)缺少LANG
环境变量。
在重新运行迁移之前设置并LANG
重新en_US.UTF-8
启动容器可以解决问题。
解决方案 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:
这里的许多答案(例如@agf 和@Andbdrew)已经解决了 OP 问题的最直接方面。
然而,我认为有一个微妙但重要的方面在很大程度上被忽略了,而对于像我一样试图理解 Python 编码的人来说,这一点非常重要:Python 2 和 Python 3 对字符表示的管理截然不同。我觉得造成这种困惑的很大一部分原因是人们在阅读 Python 编码时不了解版本。
我建议任何有兴趣了解 OP 问题根本原因的人首先阅读Spolsky 的字符表示和 Unicode 简介,然后转到Python 2 和 Python 3 中的 Unicode 上的Batchelder 。
解决方案 28:
尽量避免将变量转换为 str(variable)。有时,这可能会导致问题。
简单的避免技巧:
try:
data=str(data)
except:
data = data #Don't convert to String
上面的例子也将解决编码错误。
解决方案 29:
如果有类似的内容packet_data = "This is data"
,请在初始化之后在下一行执行以下操作packet_data
:
unic = u''
packet_data = unic
解决方案 30:
当使用 Apache 部署 django 项目时,经常会发生此问题。因为 Apache 在 /etc/sysconfig/httpd 中设置了环境变量 LANG=C。只需打开文件并注释(或更改为您的风格)此设置。或者使用 WSGIDaemonProcess 命令的 lang 选项,在这种情况下,您将能够为不同的虚拟主机设置不同的 LANG 环境变量。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件