Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7 为什么ElementTree用“拒绝”拒绝UTF-16 XML声明;编码不正确;?_Python 2.7_Unicode_Encoding_Elementtree_Python Unicode - Fatal编程技术网

Python 2.7 为什么ElementTree用“拒绝”拒绝UTF-16 XML声明;编码不正确;?

Python 2.7 为什么ElementTree用“拒绝”拒绝UTF-16 XML声明;编码不正确;?,python-2.7,unicode,encoding,elementtree,python-unicode,Python 2.7,Unicode,Encoding,Elementtree,Python Unicode,在Python 2.7中,当将unicode字符串传递给ElementTree的fromstring()方法时,该方法在XML声明中具有encoding=“UTF-16”,我得到一个ParseError,表示指定的编码不正确: >>> from xml.etree import ElementTree >>> data = u'<?xml version="1.0" encoding="utf-16"?><root/>' >>

在Python 2.7中,当将unicode字符串传递给ElementTree的
fromstring()
方法时,该方法在XML声明中具有
encoding=“UTF-16”
,我得到一个ParseError,表示指定的编码不正确:

>>> from xml.etree import ElementTree
>>> data = u'<?xml version="1.0" encoding="utf-16"?><root/>'
>>> ElementTree.fromstring(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files (x86)\Python 2.7\lib\xml\etree\ElementTree.py", line 1300, in XML
    parser.feed(text)
  File "C:\Program Files (x86)\Python 2.7\lib\xml\etree\ElementTree.py", line 1642, in feed
    self._raiseerror(v)
  File "C:\Program Files (x86)\Python 2.7\lib\xml\etree\ElementTree.py", line 1506, in _raiseerror
    raise err
xml.etree.ElementTree.ParseError: encoding specified in XML declaration is incorrect: line 1, column 30
>来自xml.etree导入元素树
>>>数据=u''
>>>ElementTree.fromstring(数据)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“C:\ProgramFiles(x86)\Python 2.7\lib\xml\etree\ElementTree.py”,第1300行,xml格式
parser.feed(文本)
文件“C:\ProgramFiles(x86)\Python2.7\lib\xml\etree\ElementTree.py”,第1642行,在提要中
自我提升错误(v)
文件“C:\Program Files(x86)\Python 2.7\lib\xml\etree\ElementTree.py”,第1506行,在\u raiseerror中
提出错误
xml.etree.ElementTree.ParseError:xml声明中指定的编码不正确:第1行第30列
这是什么意思?是什么让ElementTree这么想的

毕竟,我传递的是unicode代码点,而不是字节字符串。这里不涉及编码。怎么可能不正确呢

当然,有人可能会说任何编码都是不正确的,因为这些unicode代码点没有编码。然而,为什么UTF-8没有被拒绝为“不正确的编码”

>ElementTree.fromstring(u'')
我可以通过将unicode字符串编码为UTF-16编码的字节字符串并将其传递给
fromstring()
或将unicode字符串中的
encoding=“UTF-16”
替换为
encoding=“UTF-8”
来轻松解决此问题,但我想了解为什么会出现此异常。代码没有说明只接受字节字符串


具体地说,我希望避免这些额外的操作,因为我的输入数据可能会变得非常大,我希望避免在内存中使用它们两次,并避免处理它们的CPU开销超过绝对必要的程度。

我不会试图证明这种行为是正确的,但要解释为什么编写的代码会发生这种情况

简而言之:Python使用的XML解析器是对字节而不是unicode字符进行操作的。在将字符串传递到
元素树之前,必须调用字符串上的
.encode('utf-16-be')
.encode('utf-16-le')

ElementTree.fromstring(data.encode('utf-16-be'))

证明:
ElementTree.fromstring
最终调用
pyexpat.xmlparser.Parse
,该函数在pyexpat.c中实现:

static PyObject *
xmlparse_Parse(xmlparseobject *self, PyObject *args)
{
    char *s;
    int slen;
    int isFinal = 0;

    if (!PyArg_ParseTuple(args, "s#|i:Parse", &s, &slen, &isFinal))
        return NULL;

    return get_parse_result(self, XML_Parse(self->itself, s, slen, isFinal));
}
因此,您传入的unicode参数将使用
s.
进行转换。for
PyArg\u语法元组
说:

s#(字符串、Unicode或任何与读取缓冲区兼容的对象)[const char *,int(或Py_ssize_t,见下文)]s上的这个变量存储到两个C变量中,第一个是指向字符串的指针,第二个是 一个是它的长度。在这种情况下,Python字符串可能包含嵌入的 空字节Unicode对象传回一个指向默认编码对象的指针 对象的字符串版本,如果可以进行这种转换。全部的 其他与读取缓冲区兼容的对象将引用传递回原始缓冲区 内部数据表示

让我们看看这个:

from xml.etree import ElementTree
data = u'<?xml version="1.0" encoding="utf-8"?><root>\u2163</root>'
print ElementTree.fromstring(data)
这意味着,当您指定
encoding=“utf-8”
时,您很幸运,当Unicode字符串被编码为ASCII时,您的输入中没有非ASCII字符。如果在解析之前添加以下内容,UTF-8将与该示例的预期效果一样:

import sys
reload(sys).setdefaultencoding('utf8')

但是,将defaultencoding设置为“utf-16-be”或“utf-16-le”不起作用,因为ElementTree的Python位执行直接字符串比较,但在utf-16 land中开始失败。

感谢您的深入分析!听起来ET文档的补丁提交是有序的。:)如何从文件而不是字符串中使用此选项?
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2163' in position 44: ordinal not in range(128)
import sys
reload(sys).setdefaultencoding('utf8')