Risks related to overriding attribute access
I'd start with the caveat that you're buying some syntax sugar at the cost of possible bugs - the need to do the attribute resolution, and as you point out the possibility of name clashes, makes it seem like it may not be worth the effort unless you need to access these class properties in lots of places in your code.  

That said you can simplify this by converting your sections - which are dictionaries -- to namedtuples:

from collections import namedtuple

def section2dict(self, secname):
   if secname in self.__dict__:
      raise KeyError, "%s is cannot be used as a property name" % secname        
      opts = self.options(secname)
      #nb: I didn't bother recreating the type code, but you would do it here...
      nt = namedtuple(secname, opts.keys())(**opts)
      self.__dict__[secname] = nt


By sticking the result into dict you don't have to override getattr yourself, which limits the intervention to a single place although it does deprive you of the option to do guard checks for bad values, etc.   This example would except on name collisions and get you off the hook for manually redirecting double-dotted attribute queries.