在python中使用XML中的unicode字符:';ascii';编解码器可以';t编码位置0-3的字符:序号不在范围内(128)

在python中使用XML中的unicode字符:';ascii';编解码器可以';t编码位置0-3的字符:序号不在范围内(128),python,django,unicode,Python,Django,Unicode,我使用django,在我看来,我需要以XML的形式发送一个请求,并使用post方法从html页面接收一些unicode字符。我尝试了以下方法(请注意,我将该输入保存在fname变量中): 及 及 每次我遇到这个错误: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128) 我用这个代码解决了这个问题: fname = fname.encode('ascii', 'xmlcharrefrep

我使用django,在我看来,我需要以XML的形式发送一个请求,并使用post方法从html页面接收一些unicode字符。我尝试了以下方法(请注意,我将该输入保存在fname变量中):

每次我遇到这个错误:

'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

我用这个代码解决了这个问题:

fname = fname.encode('ascii', 'xmlcharrefreplace')
xml = r"""my XML code with unicode {0} """.format(fname)
>>> "{0}".format(u"\U0001F384"*4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
谢谢你的帮助

更新: 您可以删除或替换像>&<这样的特殊字符(感谢@bobince注意到这一点):

fname=fname.replace(“,”)
fname=fname.replace(&,“”)

您可以执行以下操作:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')
但这是一个只在python 2.7中起作用的丑陋的黑客行为


它将绕过错误,但仍可能看起来很混乱。如果要发布到html文件,请使用字符集utf-8,您可以使用以下代码重现错误:

fname = fname.encode('ascii', 'xmlcharrefreplace')
xml = r"""my XML code with unicode {0} """.format(fname)
>>> "{0}".format(u"\U0001F384"*4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
您可以使用
xml.etree.ElementTree
模块来构建xml文档,而不是字符串格式。xml是一种复杂的格式;很容易出错
ElementTree
还将正确地将Unicode字符串序列化为字节,确保xml声明中的字符编码与文档中使用的实际编码一致

xml = r"""my XML code with unicode {0} """.format(fname)
.format
方法始终生成与输入格式字符串相同的输出字符串类型。在这种情况下,格式字符串是字节字符串
r”““…”
,因此,如果
fname
是Unicode字符串,Python会尝试将其强制为字节字符串。如果
frame
包含默认编码(ASCII)中不存在的字符,则使用bang

请注意,这不同于旧的字符串格式运算符
%
,该运算符在使用的格式字符串或任何参数为Unicode时尝试升级为Unicode字符串,在这种情况下,只要
我的XML代码
与ASCII兼容,该运算符就可以工作。当您将使用
%
的代码转换为
.format()
时,这是一个常见问题

这应该很好:

xml = ur"""my XML code with unicode {0} """.format(fname)
但是,输出将是一个Unicode字符串,因此无论您接下来做什么,都需要处理这个问题(例如,如果您将其写入字节流/文件,则可能需要
。对整个过程进行编码('utf-8')
)。或者对其进行适当编码以获得字节字符串:

xml = r"""my XML code with unicode {0} """.format(fname.encode('utf-8'))
请注意,以上内容:

fname = u"%s".encode('utf8') % (fname)
无法工作,因为您正在将格式字符串编码为字节,而不是
fname
参数。这与只说
fname='%s'%fname
,实际上是
fname=fname


我用这个代码解决了这个问题:

fname = fname.encode('ascii', 'xmlcharrefreplace')
xml = r"""my XML code with unicode {0} """.format(fname)
>>> "{0}".format(u"\U0001F384"*4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
这闻起来很难闻。对于输入
hello☃,您现在正在生成
hello☃而不是正常的输出
hello☃

如果两者都
在输出中看起来与您相同,那么您可能正在执行以下操作:

xml = '<element>{0}</element>'.format(some_text)
xml='{0}'。格式(一些文本)

对于XML特殊字符,例如
&
什么
type
fname
变量
str
字节
?看起来您正在尝试将Unicode字符转换为超出其7位范围的ASCII字符。线索在错误消息中。fname是一个波斯字符串“محمدحسین”,我的意思是unicode:)不要更改默认编码。它可能会破坏不需要它的库。在这种情况下,它是不必要的。因此,丑陋,这就是为什么我添加了“或”的原因,因为我指出OP将未替换的
fname
插入到xml中。明确地说:与
%
相比,
.format()
拒绝将结果隐式升级为Unicode是一个优势。感谢您的回答。您能解释一下如何转义这些特殊字符吗?
text.replace('&','&;')。replace(''',')。replace('''','''')。replace(''''','''')。replace('''','''','&apos;'))
fname = u"%s".encode('utf8') % (fname)
fname = fname.encode('ascii', 'xmlcharrefreplace')
xml = '<element>{0}</element>'.format(some_text)