Как найти полное имя в Python: __module__ и __qualname__

Раздел: Основы Python -> Именование

Полное имя объекта в Python

Под полным именем (fully qualified name) понимается цепочка имен, однозначно идентифицирующая объект в иерархии модулей, классов и вложенных сущностей. Например, для метода draw класса Circle из модуля shapes полное имя будет shapes.Circle.draw. Знание полного имени помогает при логировании, отладке, сериализации и автоматической генерации документации.

В Python каждый объект, определённый на уровне модуля или класса, хранит служебные атрибуты: __name__, __qualname__ и __module__. Их комбинация и даёт полное квалифицированное имя.

Как получить полное имя функции, метода или класса, включая модуль?

Надёжный способ - соединить атрибуты __module__ и __qualname__ через точку.

def my_func(): pass
class A:
    def method(self): pass
    class Inner:
        def inner_method(self): pass

for obj in (my_func, A.method, A, A.Inner.inner_method):
    full_name = f"{obj.__module__}.{obj.__qualname__}"
    print(full_name)

полное имя python (полное имя в python)

__main__.my_func
__main__.A.method
__main__.A
__main__.A.Inner.inner_method

Python set name (установка имени в python)

Пояснение: __module__ содержит имя модуля (здесь __main__ при запуске скрипта), __qualname__ - полное имя относительно пакета с учётом вложенности классов. Если объект определён во внешнем модуле, __module__ будет соответствующим (например, math.sin).

Типичные проблемы

  • Лямбды: у лямбда-функций __qualname__ возвращает '<lambda>', что неинформативно. Решение - при необходимости присвоить лямбде имя через lambda name: ... или создать обычную функцию.
  • Декораторы: декоратор без @functools.wraps заменяет атрибуты декорируемой функции на свои. Тогда __qualname__ и __module__ указывают на обёртку, а не на оригинал. Решение - использовать functools.wraps(original) в декораторе.
  • Встроенные функции: у некоторых встроенных объектов (len, print) нет атрибута __module__ и __qualname__. Для них полное имя можно получить через __name__ (например, 'builtins.print'), но явного модуля может не быть.

Как получить полное имя объекта, если он был импортирован и неизвестен его модуль?

Используйте модуль inspect.getmodule(obj) для получения модуля, а затем его атрибут __name__. Комбинируйте с __qualname__.

import inspect
import math

def get_full_name(obj):
    module = inspect.getmodule(obj)
    if module:
        module_name = module.__name__
    else:
        module_name = 'builtins' if hasattr(obj, '__name__') else 'unknown'
    qualname = getattr(obj, '__qualname__', getattr(obj, '__name__', str(obj)))
    return f"{module_name}.{qualname}"

print(get_full_name(math.sin))
print(get_full_name(len))
math.sin
builtins.len

Пояснение: inspect.getmodule ищет модуль по словарю sys.modules, сопоставляя объект с его кодом. Для встроенных функций модуль не находится, поэтому в примере используется запасное значение 'builtins'.

Как получить полное имя экземпляра произвольного класса?

У экземпляра нет атрибутов __qualname__ и __module__. Нужно получить их от его класса через obj.__class__.

class MyClass:
    pass

instance = MyClass()
full_name = f"{instance.__class__.__module__}.{instance.__class__.__qualname__}"
print(full_name)
__main__.MyClass

Как получить полное имя самого выполняющегося скрипта или текущего модуля?

Воспользуйтесь глобальной переменной __name__ и, если нужно, __file__ для пути.

print("Полное имя модуля:", __name__)
print("Путь к файлу:", __file__)
Полное имя модуля: __main__
Путь к файлу: /home/user/script.py

При запуске python -m package.module __name__ будет package.module, а __file__ - абсолютный путь к файлу модуля.

Пример
# Пример 1: Рекурсивное получение полного имени для вложенных классов и методов
class Outer:
    class Middle:
        class Inner:
            def method(self): pass

        def middle_method(self): pass

def get_full_name_recursive(obj, _cache=None):
    if _cache is None:
        _cache = {}
    qualname = getattr(obj, '__qualname__', None)
    module = getattr(obj, '__module__', None)
    if qualname and module:
        return f"{module}.{qualname}"
    # Для экземпляров берем класс
    if not hasattr(obj, '__qualname__'):
        return get_full_name_recursive(type(obj), _cache)
    return str(obj)

outer_inst = Outer()
inner_inst = outer_inst.Middle.Inner()
print(get_full_name_recursive(outer_inst))
print(get_full_name_recursive(inner_inst))
print(get_full_name_recursive(Outer.Middle.Inner.method))
__main__.Outer
__main__.Outer.Middle.Inner
__main__.Outer.Middle.Inner.method
Пример
# Пример 2: Использование inspect.getmembers для вывода всех полных имён в модуле
import inspect
import math
import os

my_module = os
members = inspect.getmembers(my_module, inspect.isfunction)
for name, func in members[:3]:  # первые три функции
    try:
        full = f"{my_module.__name__}.{func.__qualname__}"
        print(full)
    except AttributeError:
        pass
os.abort
os.access
os.chdir
Пример
# Пример 3: Декоратор, сохраняющий полное имя оригинальной функции
import functools

def preserve_fullname(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Вызывается {func.__module__}.{func.__qualname__}")
        return func(*args, **kwargs)
    # явно копируем атрибуты, хотя @functools.wraps уже это делает
    wrapper.__qualname__ = func.__qualname__
    wrapper.__module__ = func.__module__
    return wrapper

@preserve_fullname
def example(x):
    return x * 2

print(example(5))
print("Имя обёртки:", example.__qualname__)
Вызывается __main__.example
10
Имя обёртки: example
Пример
# Пример 4: Получение полного имени для объекта, переданного в функцию
import builtins

def full_name_of(obj):
    if isinstance(obj, type):
        name = getattr(obj, '__qualname__', obj.__name__)
        module = getattr(obj, '__module__', 'builtins')
    elif hasattr(obj, '__class__'):
        name = obj.__class__.__qualname__
        module = obj.__class__.__module__
    else:
        name = type(obj).__name__
        module = 'builtins'
    return f"{module}.{name}"

print(full_name_of(builtins.int))
print(full_name_of("привет"))
print(full_name_of(42))
builtins.int
builtins.str
builtins.int
Пример
# Пример 5: Сравнение __name__ и __qualname__ для вложенных функций и лямбд
def outer():
    def inner():
        pass
    lam = lambda: None
    return inner, lam

inner_func, lam_func = outer()
print("Обычная вложенная:")
print("  __name__:", inner_func.__name__)
print("  __qualname__:", inner_func.__qualname__)
print("Лямбда:")
print("  __name__:", lam_func.__name__)
print("  __qualname__:", lam_func.__qualname__)
Обычная вложенная:
  __name__: inner
  __qualname__: outer.<locals>.inner
Лямбда:
  __name__: <lambda>
  __qualname__: <lambda>

Из примера видно, что __qualname__ для внутренней функции содержит цепочку outer.<locals>.inner, а для лямбды - только <lambda>. Для получения полного имени лямбды с указанием места определения можно использовать inspect.getsource (если доступен) или явно хранить имя.

Полное имя в Python - comments

En
полное имя python (python)