Путь к пакетам Python: работа с site packages

Раздел: Разработка на Python -> Пути пакетов

Основные аспекты site packages

Каталог site packages это место, где Python хранит сторонние библиотеки после установки. Знание его расположения помогает отладить импорты, управлять версиями и создавать изолированные окружения.

Как получить текущий путь к site packages прямо из кода Python?

Самый надёжный способ использовать модуль site, специально предназначенный для работы с путями установки пакетов. Функция getsitepackages возвращает список всех каталогов site packages для текущей интерпретации.

import site
print(site.getsitepackages())

Site packages python (каталог site-packages в python)

['/usr/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages']

Другой распространённый метод обратиться к sys.path и отфильтровать записи, заканчивающиеся на site-packages.

import sys
paths = [p for p in sys.path if 'site-packages' in p]
print(paths)
['/usr/lib/python3.10/site-packages']

Типичная проблема: в виртуальном окружении site.getsitepackages() может показывать пути системного Python, а не окружения. Выход использовать site.USER_SITE или проверять sys.prefix.

Как узнать site packages из командной строки без запуска скрипта?

Запустите команду python -m site она выведет подробную информацию о всех путях, используемых интерпретатором.

python -m site
sys.path = [
    '/home/user/project',
    '/usr/lib/python310.zip',
    '/usr/lib/python3.10',
    '/usr/lib/python3.10/lib-dynload',
    '/usr/lib/python3.10/site-packages',
]
USER_BASE: '/home/user/.local' (exists)
USER_SITE: '/home/user/.local/lib/python3.10/site-packages' (exists)
ENABLE_USER_SITE: True

Более компактный вариант: python -c "import sys; print([p for p in sys.path if 'packages' in p])".

Типичная ошибка: если команда выполняется в окружении без прав на запись, USER_SITE может быть не создан. Решение предварительно выполнить python -m site --user-site или явно указать --user при установке.

Как добавить собственную папку в site packages для поиска модулей?

Есть несколько способов добавить путь, не перемещая файлы. Первый установить переменную окружения PYTHONPATH.

export PYTHONPATH=/home/user/my_libs:/other/path
python my_script.py

Второй положить в любую директорию из site packages файл с расширением .pth, содержащий нужные пути.

echo '/home/user/my_libs' > /usr/lib/python3.10/site-packages/mypaths.pth

Третий самый гибкий изменять sys.path динамически в начале скрипта.

import sys
sys.path.insert(0, '/home/user/my_libs')
import mymodule

Типичная проблема: при использовании insert(0, ...) возможно перекрытие стандартных модулей. Решение добавлять путь в конец списка или использовать site.addsitedir для обработки .pth файлов.

Как найти физическое расположение уже установленного пакета в site packages?

Многие пакеты имеют атрибут __file__ в главном модуле. Например, для requests.

import requests
print(requests.__file__)
/usr/lib/python3.10/site-packages/requests/__init__.py

Для поиска без импорта используют importlib.util.find_spec.

import importlib.util
spec = importlib.util.find_spec('requests')
print(spec.origin)
/usr/lib/python3.10/site-packages/requests/__init__.py

Типичная ошибка: если пакет является namespace package, то origin может быть None. Тогда надо смотреть spec.submodule_search_locations.

Как изменить каталог site packages по умолчанию, например, для изоляции проектов?

Лучший способ использовать виртуальные окружения. При активации venv site packages создаётся внутри окружения, и системные пути не мешают.

python -m venv myenv
source myenv/bin/activate
python -c "import sys; print(sys.path)"
['', '/home/user/myenv/lib/python3.10/site-packages', ...]

Для одноразовых скриптов удобна установка с флагом --user пакеты попадают в USER_SITE.

pip install --user requests

Типичная проблема: изменение системного site packages вручную может нарушить работу других приложений. Выход всегда использовать virtualenv или venv.

Расширенные примеры работы с site packages

1. Создание собственного .pth файла и проверка его загрузки

Создадим файл mypath.pth в каталоге site packages, добавим в него путь к папке с модулями, а затем убедимся, что путь подхватился.

Пример
import sys, os, site

# Определяем каталог site packages (первый из списка)
site_packages = site.getsitepackages()[0]
pth_path = os.path.join(site_packages, 'custom.pth')

# Записываем путь, например, к /tmp/my_libs
with open(pth_path, 'w') as f:
    f.write('/tmp/my_libs\n')

# Принудительно перечитываем .pth файлы (в текущей сессии не обязательно)
# site.addsitedir(site_packages)

# Проверяем, что /tmp/my_libs появился в sys.path
print('/tmp/my_libs' in sys.path)
True

После этого все модули из /tmp/my_libs станут доступны для импорта.

2. Получение списка всех установленных в site packages пакетов с версиями

Модуль importlib.metadata (Python 3.8+) позволяет получить метаданные всех пакетов.

Пример
import importlib.metadata as md

for dist in md.distributions():
    if dist.metadata['Name']:
        print(f"{dist.metadata['Name']} == {dist.version}")
requests == 2.31.0
numpy == 1.24.3
...

Аналогичный результат даёт pkg_resources из setuptools.

3. Поиск всех файлов .py внутри site packages

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

Пример
import site, os
site_packages = site.getsitepackages()[0]
py_files = []
for root, dirs, files in os.walk(site_packages):
    for file in files:
        if file.endswith('.py'):
            py_files.append(os.path.join(root, file))
print(f"Найдено {len(py_files)} .py файлов")
print(py_files[:5])
Найдено 1243 .py файлов
['/usr/lib/python3.10/site-packages/requests/__init__.py', ...]

4. Имитация установки пакета в site packages через копирование

Иногда требуется временно добавить пакет без pip.

Пример
import sys, shutil, tempfile, os, site

# Создаём простой модуль
tmpdir = tempfile.mkdtemp()
mod_path = os.path.join(tmpdir, 'my_dummy.py')
with open(mod_path, 'w') as f:
    f.write("def greet(): return 'Hello from site packages!\n")

# Копируем в site packages (требуются права)
site_pkg = site.getsitepackages()[0]
try:
    shutil.copy(mod_path, os.path.join(site_pkg, 'my_dummy.py'))
    # Импортируем
    import my_dummy
    print(my_dummy.greet())
except PermissionError:
    print("Нет прав на запись в site packages. Используйте --user или виртуальное окружение.")
finally:
    # Удаляем временные файлы
    if os.path.exists(os.path.join(site_pkg, 'my_dummy.py')):
        os.remove(os.path.join(site_pkg, 'my_dummy.py'))
    shutil.rmtree(tmpdir)
Hello from site packages!

5. Сравнение sys.path в обычном и виртуальном окружении

Покажем разницу.

Пример
import sys
print("Обычный sys.path:", sys.path[:3])

# Создадим временное venv и выполним тот же код внутри
# (в реальном скрипте это не получится, демонстрация концепции)
Обычный sys.path: ['', '/usr/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages']

В виртуальном окружении sys.path будет указывать только на lib/python3.10/site-packages внутри папки окружения.

Каталог site-packages в Python - comments

En
Site packages python (python)