Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't set attributes on ElementTree.Element instance in Python 3

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.

like image 475
Maxim Avatar asked Nov 01 '22 07:11

Maxim


2 Answers

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
like image 56
Corley Brigman Avatar answered Nov 13 '22 02:11

Corley Brigman


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.

like image 31
RandomName Avatar answered Nov 13 '22 02:11

RandomName