XPathFunctionError on second call with user functions
Hi, When using a custom XPath function (as lxml.cssselect does for lower-case) I get a strange XPathFunctionError error when using a compiled XPath object more than once. Here is a minimal test case: from lxml import etree, html def _make_lower_case(context, s): return s.lower() ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/') ns.prefix = 'css' ns['lower-case'] = _make_lower_case #doc = html.parse('/home/simon/css3-backgrounds.html') doc = html.parse('http://www.w3.org/TR/css3-background/') expr = etree.XPath('//*[css:lower-case(name(.)) = "li"]') print('first call') expr(doc) print('second call') expr(doc) print('third call') expr(doc) And the output I get with lxml 2.3.4: first call second call Traceback (most recent call last): File "xpath_lower.py", line 20, in <module> expr(doc) File "xpath.pxi", line 466, in lxml.etree.XPath.__call__ (src/lxml/lxml.etree.c:119238) File "xpath.pxi", line 235, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:117011) File "lxml.etree.pyx", line 280, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:7454) lxml.etree.XPathFunctionError: XPath function '{b'\xd0\x85?\x01'}b'lower-case'' not found Note that the '\xd0\x85?\x01' string looks random and changes every time I run the script. Is something wrong in my code? Regards, -- Simon Sapin
Le 10/05/2012 11:59, Simon Sapin a écrit :
Hi,
When using a custom XPath function (as lxml.cssselect does for lower-case) I get a strange XPathFunctionError error when using a compiled XPath object more than once.
Here is a minimal test case:
from lxml import etree, html
def _make_lower_case(context, s): return s.lower()
ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/') ns.prefix = 'css' ns['lower-case'] = _make_lower_case
#doc = html.parse('/home/simon/css3-backgrounds.html') doc = html.parse('http://www.w3.org/TR/css3-background/')
expr = etree.XPath('//*[css:lower-case(name(.)) = "li"]') print('first call') expr(doc) print('second call') expr(doc) print('third call') expr(doc)
And the output I get with lxml 2.3.4:
first call second call Traceback (most recent call last): File "xpath_lower.py", line 20, in<module> expr(doc) File "xpath.pxi", line 466, in lxml.etree.XPath.__call__ (src/lxml/lxml.etree.c:119238) File "xpath.pxi", line 235, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:117011) File "lxml.etree.pyx", line 280, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:7454) lxml.etree.XPathFunctionError: XPath function '{b'\xd0\x85?\x01'}b'lower-case'' not found
Note that the '\xd0\x85?\x01' string looks random and changes every time I run the script.
Is something wrong in my code?
In case it helps, here are the version numbers: Python : sys.version_info(major=3, minor=2, micro=3, releaselevel='final', serial=0) lxml.etree : (2, 3, 4, 0) libxml used : (2, 7, 8) libxml compiled : (2, 7, 8) libxslt used : (1, 1, 26) libxslt compiled : (1, 1, 26) This is on Linux x64 and the random string is always 4 bytes long. I’ve seen similar issues that were caused by a 32bit vs. 64bit bug where sizeof(int) (8 in 64bit) in was used instead of sizeof(int32) or similar. -- Simon Sapin
Simon Sapin, 10.05.2012 13:45:
Le 10/05/2012 11:59, Simon Sapin a écrit :
When using a custom XPath function (as lxml.cssselect does for lower-case) I get a strange XPathFunctionError error when using a compiled XPath object more than once.
Here is a minimal test case:
from lxml import etree, html
def _make_lower_case(context, s): return s.lower()
ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/') ns.prefix = 'css' ns['lower-case'] = _make_lower_case
#doc = html.parse('/home/simon/css3-backgrounds.html') doc = html.parse('http://www.w3.org/TR/css3-background/')
expr = etree.XPath('//*[css:lower-case(name(.)) = "li"]') print('first call') expr(doc) print('second call') expr(doc) print('third call') expr(doc)
And the output I get with lxml 2.3.4:
first call second call Traceback (most recent call last): File "xpath_lower.py", line 20, in<module> expr(doc) File "xpath.pxi", line 466, in lxml.etree.XPath.__call__ (src/lxml/lxml.etree.c:119238) File "xpath.pxi", line 235, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:117011) File "lxml.etree.pyx", line 280, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:7454) lxml.etree.XPathFunctionError: XPath function '{b'\xd0\x85?\x01'}b'lower-case'' not found
Note that the '\xd0\x85?\x01' string looks random and changes every time I run the script.
Thanks for the report, I can reproduce this with the latest master branch. Don't have the time to look into it right now, but I'll give it a try further down this month. You could try running it through valgrind which often comes up with a good hint. There's a command line example in the Makefile.
In case it helps, here are the version numbers:
Python : sys.version_info(major=3, minor=2, micro=3, releaselevel='final', serial=0) lxml.etree : (2, 3, 4, 0) libxml used : (2, 7, 8) libxml compiled : (2, 7, 8) libxslt used : (1, 1, 26) libxslt compiled : (1, 1, 26)
This is on Linux x64 and the random string is always 4 bytes long. I’ve seen similar issues that were caused by a 32bit vs. 64bit bug where sizeof(int) (8 in 64bit) in was used instead of sizeof(int32) or similar.
I'd be surprised if it was something like this. Stefan
Le 10/06/2012 09:35, Stefan Behnel a écrit :
This is on Linux x64 and the random string is always 4 bytes long. I’ve seen similar issues that were caused by a 32bit vs. 64bit bug where sizeof(int) (8 in 64bit) in was used instead of sizeof(int32) or similar. I'd be surprised if it was something like this.
Maybe it is not, but the length of 4 seemingly-random bytes is very consistent. I’ll give Valgrind a try. -- Simon Sapin
participants (2)
-
Simon Sapin
-
Stefan Behnel