PyTables User's Guide: Hierarchical datasets in Python - Release 1.3.3
Prev | Chapter 4. Library Reference | Next

# 4.15. The AttributeSet class

Represents the set of attributes of a node (Leaf or Group). It provides methods to create new attributes, open, rename or delete existing ones.

Like in `Group` instances, `AttributeSet` instances make use of the natural naming convention, i.e. you can access the attributes on disk like if they were normal `AttributeSet` attributes. This offers the user a very convenient way to access (but also to set and delete) node attributes by simply specifying them like a normal attribute class.

Caveat emptor: All Python data types are supported. In particular, multidimensional `numarray` objects are saved natively as multidimensional objects in the HDF5 file. Python strings are also saved natively as HDF5 strings, and loaded back as Python strings. However, the rest of the data types including the Python scalar ones (i.e. Int, Long and Float) and more general objects (like `NumPy` or `Numeric`) are serialized using `cPickle`, so you will be able to correctly retrieve them only from a Python-aware HDF5 library. So, if you want to save Python scalar values and be able to read them with generic HDF5 tools, you should make use of scalar `numarray` objects (for example `numarray.array(1, type=numarray.Int64)`). In the same way, attributes in HDF5 native files will be always mapped into `numarray` objects. Specifically, a multidimensional attribute will be mapped into a multidimensional `numarray` and an scalar will be mapped into a scalar `numarray` (for example, an attribute of type `H5T_NATIVE_LLONG` will be read and returned as a `numarray.array(X, type=numarray.Int64)` scalar).

One more warning: because of the various potential difficulties in restoring a Python object stored in an attribute, you may end up getting a `cPickle` string where a Python object is expected. If this is the case, you may wish to run `cPickle.loads()` on that string to get an idea of where things went wrong, as shown in this example:

    >>> import tables
    >>>
    >>> class MyClass(object):
    ...   foo = 'bar'
    ...
    >>> # An object of my custom class.
    ... myObject = MyClass()
    >>>
    >>> h5f = tables.openFile('test.h5', 'w')
    >>> h5f.root._v_attrs.obj = myObject  # store the object
    >>> print h5f.root._v_attrs.obj.foo  # retrieve it
    bar
    >>> h5f.close()
    >>>
    >>> # Delete class of stored object and reopen the file.
    ... del MyClass, myObject
    >>>
    >>> h5f = tables.openFile('test.h5', 'r')
    >>> print h5f.root._v_attrs.obj.foo
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    AttributeError: 'str' object has no attribute 'foo'
    >>> # Let us inspect the object to see what is happening.
    ... print repr(h5f.root._v_attrs.obj)
    'ccopy_reg\n_reconstructor\np1\n(c__main__\nMyClass\np2\nc__builtin__\nobject\np3\nNtRp4\n.'
    >>> # Maybe unpickling the string will yield more information:
    ... import cPickle
    >>> cPickle.loads(h5f.root._v_attrs.obj)
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    AttributeError: 'module' object has no attribute 'MyClass'
    >>> # So the problem was not in the stored object,
    ... # but in the *environment* where it was restored.
    ... h5f.close()

## 4.15.1. AttributeSet instance variables

_v_node

  The parent node instance.

_v_attrnames

  List with all attribute names.

_v_attrnamessys

  List with system attribute names.

_v_attrnamesuser

  List with user attribute names.

## 4.15.2. AttributeSet methods

Note that this class defines the `__setattr__`, `__getattr__` and `__delattr__` and they work as normally intended. Any scalar (string, ints or floats) attribute is supported natively as an attribute. However, `(c)Pickle` is automatically used so as to serialize other kind of objects (like lists, tuples, dicts, small NumPy/Numeric/numarray objects, ...) that you might want to save. If an attribute is set on a target node that already has a large number of attributes, a `PerformanceWarning` will be issued.

With these special methods, you can access, assign or delete attributes on disk by just using the next constructs:

    		leaf.attrs.myattr = "str attr"  # Set a string (native support)
    		leaf.attrs.myattr2 = 3          # Set an integer (native support)
    		leaf.attrs.myattr3 = [3,(1,2)]  # A generic object (Pickled)
    		attrib = leaf.attrs.myattr      # Get the attribute myattr
    		del leaf.attrs.myattr           # Delete the attribute myattr

_f_copy(where)

  Copy the user attributes (as well as certain system attributes) to where object. where has to be a `Group` or `Leaf` instance.

_f_list(attrset = "user")

  Return a list of attribute names of the parent node. attrset selects the attribute set to be used. A `user` value returns only the user attributes and this is the default. `sys` returns only the system attributes. `all` returns both the system and user attributes.

_f_rename(oldattrname, newattrname)

  Rename an attribute.

Prev | Home | Next
The UnImplemented class | Up | Declarative classes