import inspect


def get_caller_name(skip=2):
    """Get the name of a caller in the format module.class.method.

    :param skip: the number of call stack levels to skip.
    :type skip: int
    :returns: str -- "<module>.<class>.<method>" or "<module>.<function>".
    """
    stack = inspect.stack()
    if len(stack) < skip + 1:
        return ""
    parentframe = stack[skip][0]

    name = []
    module = inspect.getmodule(parentframe)
    if module:
        name.append(module.__name__)

    if "self" in parentframe.f_locals:
        name.append(parentframe.f_locals["self"].__class__.__name__)
    codename = parentframe.f_code.co_name
    if codename != "<module>":
        name.append(codename)
    del parentframe
    return ".".join(name)