Получение перечня модулей Python: практическое руководство

Раздел: Основы Python -> Работа с модулями

Список модулей Python: базовые и альтернативные подходы

Термин 'список модулей Python' может означать разные наборы: встроенные модули интерпретатора, модули стандартной библиотеки, установленные дистрибутивы, модули в конкретной папке или уже загруженные в текущем процессе. Выбор способа зависит от цели: аудит окружения, диагностика импорта, построение документации или проверка зависимостей.

Основной подход для большинства задач состоит в комбинации нескольких источников. Для загруженных модулей используется sys.modules, для встроенных - sys.builtin_module_names, для установленных пакетов - importlib.metadata, для поиска по путям - pkgutil.iter_modules.

Пример получения списка уже импортированных модулей:

import sys

mods = sorted(sys.modules)
print(f'Загружено модулей: {len(mods)}')
print(mods[:15])

Python module attributes (атрибуты модуля в python)

Загружено модулей: 42
['__main__', '_abc', '_ast', '_codecs', '_collections', ...]

Python module version (версия модуля python)

Пояснение: словарь sys.modules содержит модули, которые уже были импортированы. Он не показывает модули, доступные для импорта, но еще не загруженные.

Пример вывода встроенных модулей:

import sys

for name in sys.builtin_module_names:
    print(name)

Python module cv2 (модуль cv2 (opencv) в python)

_abc
_ast
_codecs
...

Python tkinter module (модуль tkinter в python)

Для установленных дистрибутивов применяется importlib.metadata:

from importlib.metadata import distributions

packages = sorted({dist.metadata['Name'] for dist in distributions()})
print(f'Установлено дистрибутивов: {len(packages)}')
print(packages[:10])

Python types module (модуль types в python)

Установлено дистрибутивов: 25
['attrs', 'certifi', 'charset-normalizer', 'idna', 'pip', ...]

Python module windows (модуль windows для python)

Этот способ показывает имена дистрибутивов, которые могут отличаться от имен импортируемых модулей. Например, дистрибутив Pillow обычно импортируется как PIL.

Как получить список модулей стандартной библиотеки через help('modules')?

Встроенная справочная система Python содержит команду modules. Она выводит большой перечень модулей, доступных для импорта в текущем окружении.

help('modules')

Python module list (список модулей python)

Please wait a moment while I gather a list of all available modules...

__future__          _abc                _ast                ...

Module functions python (функции модуля в python)

Вариант подходит для быстрого обзора, но вывод неудобен для программной обработки. Кроме того, в некоторых окружениях команда может выполняться заметное время.

Как получить перечень установленных пакетов через pip list?

Команда pip list показывает дистрибутивы, установленные в текущем окружении. Это удобно для аудита зависимостей и переноса окружения.

pip list
Package    Version
---------- -------
pip        24.0
setuptools 69.0.0
...

Формат --format=json дает машинно-читаемый результат:

pip list --format=json
[{'name': 'pip', 'version': '24.0'}, {'name': 'setuptools', 'version': '69.0.0'}]

Важно: pip list работает с дистрибутивами, а не с именами модулей. Для одного дистрибутива может быть несколько импортируемых пакетов.

Как найти модули в конкретной папке через pkgutil.iter_modules?

Модуль pkgutil предоставляет функцию iter_modules, которая перебирает модули в указанных путях.

import pkgutil

for module in pkgutil.iter_modules(['.']):
    print(module.name, module.ispkg)
my_module False
my_package True

Параметр path может содержать список каталогов. Если параметр не указан, перебираются пути из sys.path.

import pkgutil

modules = [m.name for m in pkgutil.iter_modules()]
print(len(modules))
print(sorted(modules)[:20])
150
['__future__', '_aix_support', '_bootsubprocess', ...]

Метод не импортирует модули и не выполняет их код. Это безопасный способ обзора файловой структуры.

Как рекурсивно обойти пакеты через pkgutil.walk_packages?

Функция walk_packages выполняет рекурсивный обход пакетов и вложенных модулей.

import pkgutil

for module in pkgutil.walk_packages():
    print(module.name)
abc
aifc
...
email
email.charset
email.encoders
...

Рекурсивный обход может быть медленным и иногда вызывает импорт пакетов для получения их путей. Для больших окружений применяется ограничение по глубине или фильтрация по префиксу.

Как получить список модулей через importlib.util.find_spec?

Функция find_spec позволяет проверить, доступен ли модуль для импорта, без его загрузки.

import importlib.util

names = ['sys', 'os', 'numpy', 'unknown_module']
for name in names:
    spec = importlib.util.find_spec(name)
    print(name, spec is not None)
sys True
os True
numpy True
unknown_module False

Этот способ удобен для предварительной проверки зависимостей. Если модуль отсутствует, find_spec возвращает None.

Как получить модули, входящие в конкретный пакет?

Для обзора содержимого пакета используются атрибуты __all__, функция dir() и обход через pkgutil.

import json

print(hasattr(json, '__all__'))
print(dir(json)[:15])
False
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', ...]

Атрибут __all__ определяет имена, которые экспортируются при from package import *. Он не всегда присутствует.

import pkgutil
import email

for m in pkgutil.iter_modules(email.__path__, email.__name__ + '.'):
    print(m.name)
email.charset
email.encoders
email.errors
...

Как получить список загруженных модулей после запуска программы?

Сравнение sys.modules до и после импорта позволяет увидеть, какие модули были загружены.

import sys

before = set(sys.modules)
import xml.etree.ElementTree
after = set(sys.modules)
print(sorted(after - before))
['xml', 'xml.etree', 'xml.etree.ElementTree', ...]

Такой прием помогает анализировать скрытые зависимости и порядок загрузки.

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

  • sys.modules показывает только уже импортированные модули. Для полного списка доступных модулей требуется другой инструмент.
  • help('modules') может работать медленно и выводит текст, который сложно разбирать автоматически.
  • pkgutil.iter_modules() не импортирует модули, но может не видеть namespace-пакеты без файла __init__.py.
  • pip list отображает дистрибутивы, а не имена импортируемых модулей. Соответствие не всегда очевидно.
  • importlib.metadata находит только дистрибутивы с метаданными. Модули, добавленные вручную в sys.path, могут отсутствовать.
  • Ошибка ModuleNotFoundError возникает, когда модуль отсутствует в sys.path или не установлен.
  • В виртуальном окружении список модулей отличается от глобального Python. Команды требуется запускать в нужном окружении.
  • Некоторые модули доступны только на определенных платформах. Например, winreg присутствует в Windows, но отсутствует в Linux.

Расширенные примеры получения и обработки списков модулей Python

Ниже приведены примеры, которые показывают не только вывод списка, но и фильтрацию, экспорт, анализ зависимостей и проверку доступности модулей.

Как собрать доступные модули из sys.path?

Пример
import pkgutil

modules = []
for module in pkgutil.iter_modules():
    modules.append(module.name)

print(f'Доступно модулей: {len(modules)}')
print(sorted(modules)[:10])
Доступно модулей: 152
['__future__', '_aix_support', '_bootsubprocess', '_collections_abc', ...]

Пояснение: перебираются пути из sys.path. В список попадают модули и пакеты, которые могут быть импортированы.

Как выполнить фильтрацию модулей по префиксу?

Пример
import pkgutil

prefix = 'json'
found = [m.name for m in pkgutil.iter_modules() if m.name.startswith(prefix)]
print(found)
['json']

Пояснение: фильтрация по префиксу помогает найти модули, связанные с определенной темой или библиотекой.

Как получить версии установленных дистрибутивов?

Пример
from importlib.metadata import distributions

for dist in sorted(distributions(), key=lambda d: d.metadata['Name'].lower()):
    line = dist.metadata['Name'] + '==' + dist.version
    print(line)
attrs==23.1.0
certifi==2024.2.2
...

Пояснение: importlib.metadata возвращает объекты дистрибутивов. Их можно сортировать и выводить в формате requirements.

Как экспортировать список модулей в JSON?

Пример
import json
import pkgutil

items = []
for m in pkgutil.iter_modules():
    items.append({'name': m.name, 'is_package': m.ispkg})

with open('modules.json', 'w', encoding='utf-8') as f:
    json.dump(items, f, ensure_ascii=False, indent=2)

print('Сохранено', len(items), 'записей')
Сохранено 152 записей

Пояснение: результат можно использовать для отчетов, сравнения окружений или документации.

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

Пример
import importlib.util

def module_available(name):
    return importlib.util.find_spec(name) is not None

for name in ['sys', 'os', 'pandas', 'unknown']:
    print(name, module_available(name))
sys True
os True
pandas False
unknown False

Пояснение: функция find_spec не выполняет код модуля, поэтому проверка безопасна.

Как проанализировать зависимости дистрибутива?

Пример
from importlib.metadata import requires

deps = requires('requests')
for dep in deps:
    print(dep)
charset-normalizer (>=3.2.0,<4)
idna (>=2.5,<4)
urllib3 (>=1.21.1,<3)
certifi (>=2017.4.17)

Пояснение: requires возвращает список требований дистрибутива. Это помогает понять зависимости пакета.

Как сравнить sys.modules до и после импорта?

Пример
import sys

before = set(sys.modules)
import csv
import sqlite3
after = set(sys.modules)

new_modules = sorted(after - before)
print(new_modules)
['_sqlite3', 'csv', 'sqlite3']

Пояснение: сравнение множеств показывает модули, которые были загружены в результате импорта.

Как выполнить рекурсивный обход пакета с ограничением глубины?

Пример
import pkgutil

def walk_package(package_name, max_depth=1):
    package = __import__(package_name)
    prefix = package_name + '.'
    for m in pkgutil.walk_packages(package.__path__, prefix):
        depth = m.name.count('.') - package_name.count('.')
        if depth <= max_depth:
            print(m.name)

walk_package('email', max_depth=1)
email.charset
email.encoders
email.errors
email.feedparser
...

Пояснение: ограничение глубины уменьшает время обхода и объем вывода.

Как найти дубликаты модулей в sys.path?

Пример
import sys
from collections import defaultdict

paths = defaultdict(list)
for p in sys.path:
    paths[p].append(p)

duplicates = {k: v for k, v in paths.items() if len(v) > 1}
print(duplicates)
{}

Пояснение: дубликаты путей могут приводить к загрузке разных версий модулей. Пример показывает базовую проверку.

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

Пример
import sys
import subprocess

result = subprocess.run(
    [sys.executable, '-m', 'pip', 'list', '--format=json'],
    capture_output=True,
    text=True
)
print(result.stdout[:200])
[{'name': 'pip', 'version': '24.0'}, ...]

Пояснение: вызов pip через sys.executable гарантирует использование интерпретатора текущего окружения.

Как проанализировать импорты скрипта через modulefinder?

Пример
from modulefinder import ModuleFinder

finder = ModuleFinder()
finder.run_script('example.py')
print(len(finder.modules))
for name in list(finder.modules)[:10]:
    print(name)
25
__main__
os
sys
...

Пояснение: modulefinder анализирует импорты в скрипте и строит список модулей, которые могут быть загружены.

Как найти модули в zip-архиве?

Пример
import pkgutil
import zipfile

with zipfile.ZipFile('my_modules.zip') as zf:
    for m in pkgutil.iter_modules(zf.namelist()):
        print(m.name)
module_a
module_b
package_c

Пояснение: pkgutil.iter_modules может работать с zip-архивами, если они добавлены в sys.path или передан список имен.

Как выполнить динамический импорт модулей из списка?

Пример
import importlib

names = ['math', 'json', 'datetime']
for name in names:
    module = importlib.import_module(name)
    print(name, module.__file__ if hasattr(module, '__file__') else 'built-in')
math built-in
json /usr/lib/python3.11/json/__init__.py
datetime /usr/lib/python3.11/datetime.py

Пояснение: importlib.import_module загружает модуль по имени. Это полезно для плагинов и динамических систем.

Как получить информацию о модуле через spec?

Пример
import importlib.util

spec = importlib.util.find_spec('json')
print(spec.name)
print(spec.origin)
print(spec.submodule_search_locations)
json
/usr/lib/python3.11/json/__init__.py
_NamespacePath(['/usr/lib/python3.11/json'])

Пояснение: объект spec содержит путь к файлу, имя и другие сведения, которые помогают в диагностике импорта.

Как вывести только пакеты из общего списка?

Пример
import pkgutil

packages = [m.name for m in pkgutil.iter_modules() if m.ispkg]
print(len(packages))
print(sorted(packages)[:10])
45
['asyncio', 'collections', 'concurrent', 'ctypes', 'dbm', ...]

Пояснение: флаг ispkg позволяет отделить пакеты от одиночных модулей.

Как обнаружить namespace-пакеты?

Пример
import pkgutil

for m in pkgutil.iter_modules():
    if m.ispkg:
        print(m.name)
asyncio
collections
...

Пояснение: namespace-пакеты не всегда имеют файл __init__.py. Для их обнаружения иногда требуются дополнительные инструменты, например importlib.resources.

Как проверить конфликты имен модулей?

Пример
import sys
import os

name = 'json'
paths = []
for p in sys.path:
    candidate = p + '/' + name + '.py'
    if os.path.exists(candidate):
        paths.append(candidate)

print(paths)
['/usr/lib/python3.11/json.py']

Пояснение: если один и тот же модуль найден в нескольких каталогах, загружается первый по порядку в sys.path. Это может приводить к неожиданному поведению.

Список модулей Python - comments

En
Python module list (python)