51
import xml.etree.ElementTree as ET
e = ET.Element('Brock',Role="Bodyguard")
print bool(e)

Why is an xml.etree.ElementTree.Element considered False?

I know that I can do if e is not None to check for existence. But I would strongly expect bool(e) to return True.

supergra
  • 1,578
  • 13
  • 19
  • 8
    I would too. Was really surprised when I discovered the same behavior this morning and was happy to find this thread. – erewok Mar 19 '14 at 16:09

2 Answers2

57

As it turns out, Element objects are considered a False value if they have no children.

I found this in the source:

def __nonzero__(self):
    warnings.warn(
        "The behavior of this method will change in future versions.  "
        "Use specific 'len(elem)' or 'elem is not None' test instead.",
        FutureWarning, stacklevel=2
        )
    return len(self._children) != 0 # emulate old behaviour, for now

Even the inline comment agrees with you -- this behavior is iffy ;)

shx2
  • 61,779
  • 13
  • 130
  • 153
  • 6
    Perhaps that's supposed to be analogous to the fact that an empty list is an object, but contains nothing. I don't like that though, because then an element with a name and even an attribute (and even text inside!) is considered "empty". – supergra Nov 21 '13 at 19:39
  • 6
    That's exactly right. A `list` is a mere container, i.e. defined by its elements. That isn't the case with an `Element`, exactly for the reasons you mentioned. – shx2 Nov 21 '13 at 19:41
  • 5
    This iffy behavior cost me half a day of debugging even though I've been already bitten once by the same issue (but two months ago, managed to forgot it) – z33k Nov 05 '18 at 14:03
  • 7
    Oh, man, it's worse than you think. At least in the latest version of the source, the Element class that contains this definition [gets overridden](https://github.com/python/cpython/blob/v3.7.4/Lib/xml/etree/ElementTree.py#L1654-L1660) by an alternate version defined with the C API, which does *not* emit the warning. (I discovered this because I was going to comment about how you should enable a logger and use `logging.captureWarnings(True)` to see warnings like these, but in testing realised that I, uh, couldn't see this warning when I do that.) What a goddamned mess the whole thing is. – Mark Amery Aug 27 '19 at 15:20
21

From the docs:

http://docs.python.org/library/xml.etree.elementtree.html#element-objects

Caution: Elements with no subelements will test as False. This behavior will change in future versions. Use specific len(elem) or elem is None test instead.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
John Spong
  • 1,361
  • 7
  • 8
  • 1
    This API wart including some explanations of how it came to be is tracked in https://github.com/python/cpython/issues/83122 – gps Jan 11 '23 at 23:48