Свойства модулей в Python
Атрибуты модуля: основные понятия и способы работы
Как получить полный список атрибутов модуля и обратиться к каждому из них?
Каждый модуль в Python представляет собой объект со своим пространством имён. Атрибутами модуля являются все имена, определённые на уровне модуля: переменные, функции, классы, а также встроенные атрибуты, такие как __name__, __doc__, __file__ и другие. Для доступа к атрибутам используется синтаксис module.attribute. Для динамического обращения применяются функции getattr(), hasattr(), setattr() и dir().
Наиболее эффективный способ получить все атрибуты модуля - вызвать dir(module) или обратиться к module.__dict__. Функция dir() возвращает отсортированный список строк с именами атрибутов, включая унаследованные от встроенного типа модуля. Словарь __dict__ содержит только те имена, которые определены непосредственно в модуле, и доступен для изменений.
import math
print(dir(math)) # список атрибутов модуля math
print(math.__dict__) # словарь атрибутов модуляPython module attributes (атрибуты модуля в python)
Для проверки наличия конкретного атрибута используется hasattr(module, name). Для чтения - getattr(module, name, default). Для установки - setattr(module, name, value).
import sys
print(hasattr(sys, 'version')) # True
print(getattr(sys, 'version', 'не найден')) # версия Python
setattr(sys, 'my_custom_attr', 42)
print(sys.my_custom_attr) # 42Python module version (версия модуля python)
Как получить список атрибутов, исключая встроенные?
Можно отфильтровать имена, начинающиеся с двойного подчёркивания, или использовать vars(module), которая возвращает словарь __dict__.
import mymodule
public = [attr for attr in dir(mymodule) if not attr.startswith('_')]
print(public)Python cpp module (взаимодействие python с модулями c++)
Типичная ошибка:
При использовании from module import * импортируются только атрибуты, перечисленные в __all__. Если __all__ не определён, то импортируются все имена, не начинающиеся с подчёркивания. Это может привести к неожиданному загрязнению пространства имён. Решение - всегда явно определять __all__ в модуле.
Как получить информацию о модуле: имя, файл, документацию?
Модуль хранит метаданные во встроенных атрибутах: __name__ - имя модуля, __file__ - путь к файлу, __doc__ - строка документации, __package__ - имя пакета (для пакетов), __spec__ - объект спецификации модуля.
import os
print(os.__name__) # 'os'
print(os.__file__) # '.../os.py'
print(os.__doc__[:50])# первые 50 символовPython module cv2 (модуль cv2 (opencv) в python)
Проблема:
У встроенных модулей (например, sys) атрибут __file__ может отсутствовать или быть пустым, так как они скомпилированы в интерпретатор. Проверка hasattr(module, '__file__') перед использованием предотвращает ошибки.
Как задать версию модуля и другие пользовательские атрибуты?
Обычно определением в модуле: __version__ = '1.0.0'. Также возможно присваивание из другого модуля через setattr().
# модуль mymodule.py
__version__ = '2.1.0'
__author__ = 'Василий Петров'
# из другого файла
import mymodule
print(mymodule.__version__)
setattr(mymodule, 'release_date', '2025-04-01')
print(mymodule.release_date)Python encodings module (модуль encodings в python)
Предостережение:
Изменение атрибутов стандартных библиотечных модулей на лету может нарушить работу других частей кода или самого интерпретатора. Рекомендуется изменять только собственные модули.
Как работать с пакетами: атрибуты __path__ и __package__?
Пакет - это модуль, содержащий подмодули. Его атрибут __path__ указывает пути, где искать подпакеты, а __package__ содержит имя пакета. Для пакетов-пространств имён (namespace packages) __path__ может состоять из нескольких путей.
import xml
print(xml.__package__) # 'xml'
print(xml.__path__) # ['.../xml']Platform module python (модуль platform в python)
Как контролировать, что экспортируется из модуля?
Определением списка __all__. Он влияет только на from module import * и на функцию dir() в некоторых контекстах.
# mymodule.py
__all__ = ['func1', 'ClassA']
def func1(): pass
class ClassA: pass
def internal(): pass # не будет импортирован
# другой файл
from mymodule import *
# func1 и ClassA доступны, internal - нетОшибка:
Забыть указать __all__ и случайно сделать видимой внутреннюю функцию. Решение - всегда явно определять публичный интерфейс.
Развёрнутые примеры работы с атрибутами модулей
Пример 1. Интроспекция модуля math
Получение списка всех атрибутов модуля math, фильтрация публичных, и просмотр значения одного из них.
import math
# все атрибуты
all_attrs = dir(math)
print("Всего атрибутов:", len(all_attrs))
# только публичные (не начинаются с _)
pub_attrs = [a for a in all_attrs if not a.startswith('_')]
print("Публичные:", pub_attrs[:10], "...")
# значение атрибута pi
print("pi =", getattr(math, 'pi')) # 3.141592653589793Всего атрибутов: 65 Публичные: ['acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt', 'ceil', 'comb'] ... pi = 3.141592653589793
Пример 2. Создание модуля с пользовательскими атрибутами во время выполнения
Допустим, есть модуль config.py, в который динамически добавляются настройки из JSON-файла.
# config.py
import json
with open('settings.json', 'r') as f:
settings = json.load(f)
for key, value in settings.items():
globals()[key] = value
__all__ = list(settings.keys())(при наличии settings.json, например {"db_host": "localhost", "db_port": 5432}, после импорта config будут доступны config.db_host и config.db_port)Пример 3. Использование __all__ для ограничения экспорта
Создание модуля utils.py, где определены публичные и приватные функции.
# utils.py
__all__ = ['public_func1', 'PublicClass']
def public_func1():
return "доступна"
def _private_helper():
return "скрыта"
class PublicClass:
pass# другой файл from utils import * print(public_func1()) # работает print(_private_helper) # NameError не определена
Пример 4. Модификация атрибутов модуля во время выполнения
Изменение атрибута some_module.flag извне, что влияет на поведение функций модуля.
# controls.py
flag = False
def run():
if flag:
print("Активировано")
else:
print("Не активировано")
# main.py
import controls
controls.run() # Не активировано
controls.flag = True
controls.run() # АктивированоНе активировано Активировано
Пример 5. Работа с __path__ в пакете-пространстве имён
Создание двух каталогов, каждый из которых содержит namespace_pkg/__init__.py. При импорте пакета namespace_pkg его путь объединяется.
import namespace_pkg
print(namespace_pkg.__path__)
# ['/path/to/first/namespace_pkg', '/path/to/second/namespace_pkg'](зависит от структуры файловой системы)
Пример 6. Проверка существования атрибута с fallback
Безопасное получение версии модуля с использованием getattr.
import sys
version = getattr(sys, 'version_info', None)
if version:
print(f"Python {version.major}.{version.minor}")
else:
print("Не удалось получить версию")Python 3.12
Пример 7. Использование __spec__ для получения подробной информации о загрузке модуля
import collections
spec = getattr(collections, '__spec__', None)
if spec:
print("Имя:", spec.name)
print("Оригинальное имя:", spec.origin)
print("Подмодули:", spec.submodule_search_locations)Имя: collections Оригинальное имя: /usr/lib/python3.12/collections/__init__.py Подмодули: ['/usr/lib/python3.12/collections']