I don't understand why in Python 3 I can't add some attributes to ElementTree.Element
instances. Here is the difference:
In Python 2:
Python 2.6.6 (r266:84292, Jun 18 2012, 14:18:47)
[GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from xml.etree import ElementTree as ET
>>> el = ET.Element('table')
>>> el.foo = 50
>>> el.foo
50
>>>
In Python 3:
Python 3.3.0 (default, Sep 11 2013, 16:29:08)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from xml.etree import ElementTree as ET
>>> el = ET.Element('table')
>>> el.foo = 50
>>> el.foo
AttributeError: foo
>>>
Python 2 is provided by a distribution (CentOS). Python 3 was compiled from sources.
Is it intended behavior, a bug, or do I have to recompile python 3 with some additional flags?
UPDATE:
Some clarification: I am trying to set attributes on Python object, i.e. on Element
instance. Not XML attributes (Element.attrib
).
This issue actually arose when I tried to subclass Element
. Here is example:
>>> class Table(ET.Element):
... def __init__(self):
... super().__init__('table')
... print('calling __init__')
... self.foo = 50
...
>>> t = Table()
calling __init__
>>> t.foo
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Table' object has no attribute 'foo'
>>>
This makes me think that Element
class is instantiated in some tricky way, but I can't figure out what goes on. Hence the question.
It's probably intentional... take a look at Can't set attributes of object class . If they haven't enhanced ElementTree to use slots instead of dict in that time, i would be surprised anyways.
Not clear what you are trying to do... are you really trying to set python attributes, or XML attributes? If the latter, you really want to do this:
el = ET.Element('table')
el.set('foo', 50)
#or
el.attrib['foo'] = 50
If you really want to add python attributes, you should subclass instead, and probably provide your own Element/SubElement functions to supply the 'wrapped' elements instead of standard ones.
Update 6/4/2016: Maybe not clear from my answer, but here's what you probably need to do (I'm normally python 2.7):
class Table(ET.Element):
# Adding __slots__ gives it a known attribute to use
__slots__ = ('foo',)
def __init__(self):
super().__init__('table')
print('calling __init__')
self.foo = 50
Since 3.3 ElementTree tries to import the c implementation in for efficiency, however you can't set arbitrary attributes on that implementation. If you are in a situation where you don't want to use the Set or Get methods every time, you should use ET._Element_Py, which is the Python implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With