xotl.tools.names – Utilities for handling objects names

A protocol to obtain or manage object names.

xotl.tools.names.nameof(*objects, depth=1, inner=False, typed=False, full=False, safe=False)[source]

Obtain the name of each one of a set of objects.

New in version 1.4.0.

    Changed in version 1.6.0:
  • Keyword arguments are now keyword-only arguments.

  • Support for several objects

  • Improved the semantics of parameter full.

  • Added the safe keyword argument.

If no object is given, None is returned; if only one object is given, a single string is returned; otherwise a list of strings is returned.

The name of an object is normally the variable name in the calling stack.

If the object is not present calling frame, up to five frame levels are searched. Use the depth keyword argument to specify a different starting point and the search will proceed five levels from this frame up.

If the same object has several good names a single one is arbitrarily chosen.

Good names candidates are retrieved based on the keywords arguments full, inner, safe and typed.

If typed is True and the object is not a type name or a callable (see xotl.tools.future.inspect.safe_name()), then the type of the object is used instead.

If inner is True we try to extract the name by introspection instead of looking for the object in the frame stack.

If full is True the full identifier of the object is preferred. In this case if inner is False the local-name for the object is found. If inner is True, find the import-name.

If safe is True, returned value is converted -if it is not- into a valid Python identifier, though you should not trust this identifier resolves to the value.

See the examples in the documentation.


The names of objects imported from ‘xoutil’ are still in the namespace ‘xotl.tools’.


Build an valid identifier from the name extracted from an object.

New in version 1.5.6.

First, check if argument is a type and then returns the name of the type prefixed with _ if valid; otherwise calls nameof function repeatedly until a valid identifier is found using the following order logic: inner=True, without arguments looking-up a variable in the calling stack, and typed=True. Returns None if no valid value is found.


>>> identifier_from({})

Use cases for getting the name of an object

The function nameof() is useful for cases when you get a value and you need a name. This is a common need when doing framework-level code that tries to avoid repetition of concepts.

Solutions with nameof()

Properly calculate the tasks’ name in Celery applications

Celery warns about how to import the tasks. If in a module you import your task using an absolute import, and in another module you import it using a relative import, Celery regards them as different tasks. You must either use a consistent import style, or give a name for the task. Using nameof you can easily fix this problem.

Assume you create a celapp.tasks.basic module with this code:

>>> def celery_task(celeryapp, *args, **kwargs):
...    def decorator(func):
...        from xotl.tools.names import nameof
...        taskname = nameof(func, full=True, inner=True)
...        return celeryapp.task(name=taskname, *args, **kwargs)(func)
...    return decorator

>>> from celery import Celery
>>> app = Celery()
>>> @celery_task(app)
... def add(x, y):
...     return x + y

Then importing the task directly in a shell will have the correct name:

>>> from celapp.tasks.basic import add
>>> add.name

Another module that imports the task will also see the proper name. Say you have the module celapp.consumer:

>>> from .tasks import basic

>>> def get_name(taskname):
...     task = getattr(basic, taskname)
...     return task.name


>>> from celapp.consumer import get_name
>>> get_name('add')

Despite that you imported the basic module with a relative import the name is fully calculated.