Путь к пакетам Python: работа с site packages
Основные аспекты 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 внутри папки окружения.