I'm implementing deep_get functionality to look inside arbitrarily nested Python 2.7 objects. Primarily for further logging.
This turned out to have surprising amount of quirks. Here's what I ended up with, would appreciate the feedback as I probably missed a few more things.
# coding=utf-8
from __future__ import unicode_literals
import collections
_default_stub = object()
def deep_get(obj, path, default=_default_stub, separator='.'):
    """Gets arbitrarily nested attribute or item value.
    Args:
        obj: Object to search in.
        path (str, hashable, iterable of hashables): Arbitrarily nested path in obj hierarchy.
        default: Default value. When provided it is returned if the path doesn't exist.
            Otherwise the call raises a LookupError.
        separator: String to split path by.
    Returns:
        Value at path.
    Raises:
        LookupError: If object at path doesn't exist.
    Examples:
        >>> deep_get({'a': 1}, 'a')
        1
        >>> deep_get({'a': 1}, 'b')
        LookupError: {'a': 1} has no element at 'b'
        >>> deep_get(['a', 'b', 'c'], -1)
        'c'
        >>> deep_get({'a': [{'b': [1, 2, 3]}, 'some string']}, 'a.0.b')
        [1, 2, 3]
        >>> class A(object):
        >>>     def __init__(self):
        >>>         self.x = self
        >>>         self.y = {'a': 10}
        >>>
        >>> deep_get(A(), 'x.x.x.x.x.x.y.a')
        10
        >>> deep_get({'a.b': {'c': 1}}, 'a.b.c')
        LookupError: {'a.b': {'c': 1}} has no element at 'a'
        >>> deep_get({'a.b': {'Привет': 1}}, ['a.b', 'Привет'])
        1
        >>> deep_get({'a.b': {'Привет': 1}}, 'a.b/Привет', separator='/')
        1
    """
    if isinstance(path, basestring):
        attributes = path.split(separator)
    elif isinstance(path, collections.Iterable):
        attributes = path
    else:
        attributes = [path]
    for i in attributes:
        try:
            success = False
            # 1. access as attr
            try:
                obj = getattr(obj, i)
                success = True
            except (AttributeError, TypeError, UnicodeEncodeError):
                # 2. access as dict index
                try:
                    obj = obj[i]
                    success = True
                except (TypeError, AttributeError, IndexError, KeyError):
                    # 3. access as list index
                    try:
                        obj = obj[int(i)]
                        success = True
                    except (TypeError, AttributeError, IndexError, KeyError,
                            UnicodeEncodeError, ValueError):
                        pass
            if not success:
                msg = "{obj} has no element at '{i}'".format(obj=obj, i=i)
                raise LookupError(msg.encode('utf8'))
        except Exception:
            if _default_stub != default:
                return default
            raise
    return obj
Update: Revised version with history https://gist.github.com/groz/f1838404d48971cc145609c226fdc6a2


