/
arch_linux
/
pylibman
Обзор
Документация
Войти
/
arch_linux
/
pylibman
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
python_manager_lybirali.py
775 строк
35 KB
БАЛИЦКИЙ АЛЕКСАНДР НИКОЛАЕВИЧ
upload files
29 ноя 2025, 13:18
29 ноя 2025, 13:18
f142f94
Код
Авторство
О чём код?
import json import subprocess import sys import os import platform from pathlib import Path from typing import List, Dict, Optional import webbrowser class PythonLibraryManager: def __init__(self, requirements_file: str = "requirements.txt"): self.requirements_file = requirements_file self.os_info = self._detect_os() self.package_manager = self._detect_package_manager() self.installed_libraries = self._get_installed_libraries() def _detect_os(self) -> Dict[str, str]: """Определить операционную систему и дистрибутив""" system = platform.system().lower() release = platform.release() version = platform.version() os_info = { "system": system, "release": release, "version": version, "distro": "unknown", "pretty_name": f"{system.title()} {release}" } # Определяем дистрибутив Linux if system == "linux": try: # Попробуем прочитать информацию о дистрибутиве with open('/etc/os-release', 'r', encoding='utf-8') as f: for line in f: if line.startswith('ID='): os_info["distro"] = line.split('=')[1].strip().strip('"') elif line.startswith('PRETTY_NAME='): os_info["pretty_name"] = line.split('=')[1].strip().strip('"') except: pass elif system == "windows": os_info["pretty_name"] = f"Windows {release}" elif system == "darwin": os_info["pretty_name"] = f"macOS {release}" return os_info def _detect_package_manager(self) -> Dict[str, str]: """Определить доступные менеджеры пакетов""" # Всегда используем python -m pip для надежности python_manager = [sys.executable, "-m", "pip"] # Проверяем доступность других менеджеров managers = { "pip": self._check_command(["pip", "--version"]), "pip3": self._check_command(["pip3", "--version"]), "pipx": self._check_command(["pipx", "--version"]), "apt": self._check_command(["apt", "--version"]), "yum": self._check_command(["yum", "--version"]), "dnf": self._check_command(["dnf", "--version"]), "pacman": self._check_command(["pacman", "--version"]), "brew": self._check_command(["brew", "--version"]), "choco": self._check_command(["choco", "--version"]), "scoop": self._check_command(["scoop", "--version"]), "winget": self._check_command(["winget", "--version"]), } # Выбираем системный менеджер пакетов с приоритетом system_manager = None if self.os_info["system"] == "linux": if self.os_info["distro"] in ["ubuntu", "debian"] and managers["apt"]: system_manager = "apt" elif self.os_info["distro"] in ["centos", "rhel", "fedora"] and managers["yum"]: system_manager = "yum" elif self.os_info["distro"] == "fedora" and managers["dnf"]: system_manager = "dnf" elif self.os_info["distro"] in ["arch", "manjaro"] and managers["pacman"]: system_manager = "pacman" elif self.os_info["system"] == "darwin" and managers["brew"]: system_manager = "brew" elif self.os_info["system"] == "windows": # Приоритет для Windows: Scoop -> Chocolatey -> Winget if managers["scoop"]: system_manager = "scoop" elif managers["choco"]: system_manager = "choco" elif managers["winget"]: system_manager = "winget" return { "python": python_manager, # Теперь это список команд "system": system_manager, "available": {k: v for k, v in managers.items() if v} } def _check_command(self, command: List[str]) -> bool: """Проверить доступность команды в системе""" try: subprocess.run(command, capture_output=True, check=True) return True except (subprocess.CalledProcessError, FileNotFoundError): return False def _run_pip_command(self, args: List[str]) -> subprocess.CompletedProcess: """Запустить команду pip с правильными аргументами""" command = self.package_manager["python"] + args return subprocess.run(command, capture_output=True, text=True, check=True) def _get_installed_libraries(self) -> Dict[str, str]: """Получить список установленных библиотек и их версий""" try: result = self._run_pip_command(["list", "--format=json"]) libraries = {} for lib in json.loads(result.stdout): libraries[lib['name'].lower()] = lib['version'] return libraries except (subprocess.CalledProcessError, json.JSONDecodeError): return {} def install_library(self, library_name: str, version: Optional[str] = None) -> bool: """Умная установка библиотеки с выбором менеджера""" # Специальные случаи для разных ОС system_specific_libs = { "windows": { "pywin32": [sys.executable, "-m", "pip", "install", "pywin32"], "pyhook": [sys.executable, "-m", "pip", "install", "pyhook"], "windows-curses": [sys.executable, "-m", "pip", "install", "windows-curses"] }, "linux": { "python3-dev": ["sudo", "apt", "install", "-y", "python3-dev"], "python-devel": ["sudo", "yum", "install", "-y", "python-devel"], "python3-tk": ["sudo", "apt", "install", "-y", "python3-tk"] }, "darwin": { "pyobjc": [sys.executable, "-m", "pip", "install", "pyobjc"], "py2app": [sys.executable, "-m", "pip", "install", "py2app"] } } # Проверяем специальные случаи current_system = self.os_info["system"] if current_system in system_specific_libs and library_name in system_specific_libs[current_system]: print(f"🔧 Специальная установка для {current_system}: {library_name}") command = system_specific_libs[current_system][library_name] try: subprocess.run(command, check=True) self.installed_libraries = self._get_installed_libraries() print(f"✅ {library_name} успешно установлена") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при установке {library_name}: {e}") return False # Обычная установка через pip try: if version: package = f"{library_name}=={version}" else: package = library_name print(f"📦 Установка {package}...") self._run_pip_command(["install", package]) self.installed_libraries = self._get_installed_libraries() print(f"✅ {library_name} успешно установлена") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при установке {library_name}: {e}") # Предлагаем альтернативные способы установки self._suggest_alternative_install(library_name) return False def _suggest_alternative_install(self, library_name: str): """Предложить альтернативные способы установки""" print(f"\n💡 Альтернативные способы установки {library_name}:") system_manager = self.package_manager["system"] if system_manager == "apt": print(f" 📦 sudo apt install python3-{library_name}") print(f" 📦 sudo apt install python-{library_name}") elif system_manager == "yum" or system_manager == "dnf": print(f" 📦 sudo {system_manager} install python3-{library_name}") print(f" 📦 sudo {system_manager} install python-{library_name}") elif system_manager == "pacman": print(f" 📦 sudo pacman -S python-{library_name}") print(f" 📦 sudo pacman -S python3-{library_name}") elif system_manager == "brew": print(f" 📦 brew install python-{library_name}") elif system_manager == "scoop": print(f" 🍦 scoop install {library_name}") # Для Python библиотек через Scoop print(f" 🐍 scoop install python-{library_name}") elif system_manager == "choco": print(f" 📦 choco install {library_name}") print(f" 🐍 choco install python-{library_name}") elif system_manager == "winget": print(f" 🪟 winget install {library_name}") print(f" 🐍 winget install Python.{library_name}") # Предлагаем установить через pipx если доступен if "pipx" in self.package_manager["available"]: print(f" 🐍 pipx install {library_name}") def install_system_package(self, package_name: str) -> bool: """Установить системный пакет""" if not self.package_manager["system"]: print("❌ Системный менеджер пакетов не найден") return False try: commands = { "apt": ["sudo", "apt", "install", "-y", package_name], "yum": ["sudo", "yum", "install", "-y", package_name], "dnf": ["sudo", "dnf", "install", "-y", package_name], "pacman": ["sudo", "pacman", "-S", "--noconfirm", package_name], "brew": ["brew", "install", package_name], "scoop": ["scoop", "install", package_name], "choco": ["choco", "install", "-y", package_name], "winget": ["winget", "install", "--silent", package_name] } command = commands.get(self.package_manager["system"]) if not command: print(f"❌ Менеджер {self.package_manager['system']} не поддерживается") return False manager_name = self.package_manager["system"] manager_icon = "🍦" if manager_name == "scoop" else "🖥️" print(f"{manager_icon} Установка системного пакета {package_name} через {manager_name}...") subprocess.run(command, check=True) print(f"✅ {package_name} успешно установлен") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при установке {package_name}: {e}") # Для Scoop предлагаем обновить bucket'ы if self.package_manager["system"] == "scoop": print("\n💡 Попробуйте обновить bucket'ы Scoop:") print(" 🍦 scoop update") print(" 🍦 scoop bucket add extras") print(" 🍦 scoop bucket add versions") return False def show_scoop_buckets(self): """Показать доступные bucket'ы Scoop""" if self.package_manager["system"] != "scoop": print("❌ Scoop не используется как системный менеджер") return False try: print("🍦 Доступные bucket'ы Scoop:") result = subprocess.run(["scoop", "bucket", "list"], capture_output=True, text=True, check=True) print(result.stdout) return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при получении списка bucket'ов: {e}") return False def add_scoop_bucket(self, bucket_name: str) -> bool: """Добавить bucket в Scoop""" if self.package_manager["system"] != "scoop": print("❌ Scoop не используется как системный менеджер") return False try: print(f"🍦 Добавление bucket'а {bucket_name}...") subprocess.run(["scoop", "bucket", "add", bucket_name], check=True) print(f"✅ Bucket {bucket_name} успешно добавлен") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при добавлении bucket'а: {e}") return False def update_scoop(self) -> bool: """Обновить Scoop и bucket'ы""" if self.package_manager["system"] != "scoop": print("❌ Scoop не используется как системный менеджер") return False try: print("🍦 Обновление Scoop и bucket'ов...") subprocess.run(["scoop", "update"], check=True) print("✅ Scoop успешно обновлен") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при обновлении Scoop: {e}") return False def show_system_info(self): """Показать информацию о системе""" pretty_name = self.os_info.get('pretty_name', f"{self.os_info['system'].title()} {self.os_info['release']}") print(f"💻 Операционная система: {pretty_name}") print(f"🐍 Python команда: {' '.join(self.package_manager['python'])}") system_manager = self.package_manager['system'] if system_manager: manager_icon = "🍦" if system_manager == "scoop" else "🖥️" print(f"{manager_icon} Системный менеджер: {system_manager}") print("\n📦 Доступные менеджеры пакетов:") for manager, available in self.package_manager['available'].items(): status = "✅" if available else "❌" icon = "🍦" if manager == "scoop" else "📦" print(f" {status} {icon} {manager}") def show_about(self): """Показать информацию о программе""" print("🎯 О ПРОГРАММЕ") print("="*50) print("🐍 УМНЫЙ Менеджер библиотек Python") print("="*50) print("📝 Описание:") print(" Универсальный менеджер для управления Python библиотеками") print(" с поддержкой различных системных менеджеров пакетов") print("") print("⚡ Основные возможности:") print(" • 📥 Умная установка библиотек") print(" • 🔄 Обновление и удаление пакетов") print(" • 🖥️ Поддержка системных менеджеров") print(" • 💾 Управление зависимостями") print(" • 🔍 Поиск библиотек в PyPI") print(" • 🧹 Очистка кэша") print("") print("🛠️ Поддерживаемые менеджеры:") print(" • Python: pip, pip3, pipx") print(" • Windows: Scoop, Chocolatey, Winget") print(" • Linux: apt, yum, dnf, pacman") print(" • macOS: brew") print("") print("👨💻 Автор: Балицкий Александр") print("📅 Версия: 2025") print("="*50) # Остальные методы остаются без изменений def install_multiple_libraries(self, libraries: List[str]) -> bool: """Установить несколько библиотек за раз""" try: print(f"Установка {len(libraries)} библиотек...") for lib in libraries: print(f" 📦 {lib}") self._run_pip_command(["install"] + libraries) self.installed_libraries = self._get_installed_libraries() print("✅ Все библиотеки успешно установлены") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при установке библиотек: {e}") return False def uninstall_library(self, library_name: str) -> bool: """Удалить библиотеку""" try: print(f"🗑️ Удаление {library_name}...") self._run_pip_command(["uninstall", "-y", library_name]) self.installed_libraries = self._get_installed_libraries() print(f"✅ {library_name} успешно удалена") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при удалении {library_name}: {e}") return False def update_library(self, library_name: str) -> bool: """Обновить библиотеку до последней версии""" try: print(f"🔄 Обновление {library_name}...") self._run_pip_command(["install", "--upgrade", library_name]) self.installed_libraries = self._get_installed_libraries() print(f"✅ {library_name} успешно обновлена") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при обновлении {library_name}: {e}") return False def update_all_libraries(self) -> bool: """Обновить все установленные библиотеки""" try: print("🔍 Поиск устаревших библиотек...") result = self._run_pip_command(["list", "--outdated", "--format=json"]) outdated_libs = json.loads(result.stdout) if not outdated_libs: print("✅ Все библиотеки актуальны!") return True print(f"📦 Найдено {len(outdated_libs)} устаревших библиотек:") for lib in outdated_libs: print(f" • {lib['name']} {lib['version']} -> {lib['latest_version']}") confirm = input("\n🔄 Обновить все библиотеки? (y/N): ").strip().lower() if confirm == 'y': for lib in outdated_libs: self.update_library(lib['name']) print("✅ Все библиотеки обновлены!") return True else: print("❌ Обновление отменено") return False except subprocess.CalledProcessError as e: print(f"❌ Ошибка при обновлении библиотек: {e}") return False def search_library(self, query: str) -> List[Dict]: """Поиск библиотек в PyPI""" try: result = self._run_pip_command(["search", query]) if result.returncode == 0: libraries = [] for line in result.stdout.split('\n'): if line.strip(): parts = line.split(' - ') if len(parts) >= 2: name_version = parts[0].split() name = name_version[0] description = parts[1] libraries.append({ 'name': name, 'description': description }) return libraries return [] except subprocess.CalledProcessError: print("❌ Поиск временно недоступен") return [] def save_requirements(self) -> bool: """Сохранить текущие зависимости в requirements.txt""" try: result = self._run_pip_command(["freeze"]) with open(self.requirements_file, 'w', encoding='utf-8') as f: f.write(result.stdout) print(f"✅ Зависимости сохранены в {self.requirements_file}") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при сохранении зависимостей: {e}") return False def install_from_requirements(self) -> bool: """Установить зависимости из requirements.txt""" if not os.path.exists(self.requirements_file): print(f"❌ Файл {self.requirements_file} не найден") return False try: print(f"Установка зависимостей из {self.requirements_file}...") self._run_pip_command(["install", "-r", self.requirements_file]) self.installed_libraries = self._get_installed_libraries() print("✅ Все зависимости успешно установлены") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при установке зависимостей: {e}") return False def list_installed(self) -> None: """Показать список установленных библиотек""" if not self.installed_libraries: print("📭 Нет установленных библиотек") return print("📚 Установленные библиотеки:") for name, version in sorted(self.installed_libraries.items()): print(f" • {name} == {version}") def check_library_info(self, library_name: str) -> Optional[Dict]: """Проверить информацию о библиотеке""" library_name = library_name.lower() if library_name in self.installed_libraries: return { 'name': library_name, 'version': self.installed_libraries[library_name], 'installed': True } # Попробуем получить информацию о доступной библиотеке try: result = self._run_pip_command(["show", library_name]) if result.returncode == 0: info = {} for line in result.stdout.split('\n'): if ': ' in line: key, value = line.split(': ', 1) info[key.strip().lower()] = value.strip() return { 'name': library_name, 'version': info.get('version', 'неизвестно'), 'installed': False, 'description': info.get('summary', '') } except: pass return None def find_outdated(self) -> List[Dict]: """Найти устаревшие библиотеки""" try: result = self._run_pip_command(["list", "--outdated", "--format=json"]) return json.loads(result.stdout) except subprocess.CalledProcessError: return [] def open_pypi_page(self, library_name: str) -> bool: """Открыть страницу библиотеки на PyPI""" url = f"https://pypi.org/project/{library_name}/" try: webbrowser.open(url) print(f"🌐 Открываю страницу {library_name} на PyPI...") return True except Exception as e: print(f"❌ Не удалось открыть страницу: {e}") return False def cleanup_cache(self) -> bool: """Очистить кэш pip""" try: print("🧹 Очистка кэш pip...") self._run_pip_command(["cache", "purge"]) print("✅ Кэш успешно очищен") return True except subprocess.CalledProcessError as e: print(f"❌ Ошибка при очистке кэша: {e}") return False def clear_screen(): """Очистить экран терминала""" os.system('cls' if os.name == 'nt' else 'clear') def wait_for_enter(): """Ожидание нажатия Enter""" input("\n↵ Нажмите Enter для продолжения...") def main(): """Главная функция для работы через командную строку""" manager = PythonLibraryManager() while True: clear_screen() print("\n" + "="*60) print("🐍 УМНЫЙ Менеджер библиотек Python - Адаптивная установка") print("="*60) manager.show_system_info() print("="*60) print("1. 📥 Установить Python библиотеку") print("2. 🖥️ Установить системный пакет") print("3. 📦 Установить несколько библиотек") print("4. 🗑️ Удалить библиотеку") print("5. 🔄 Обновить библиотеку") print("6. 🚀 Обновить ВСЕ библиотеки") print("7. 📋 Список установленных библиотек") print("8. 🔍 Поиск библиотек") print("9. 📈 Найти устаревшие библиотеки") print("10. 💾 Сохранить зависимости") print("11. 📤 Установить из requirements.txt") print("12. ℹ️ Информация о библиотеке") print("13. 🌐 Открыть страницу на PyPI") print("14. 🧹 Очистить кэш pip") # Дополнительные опции для Scoop if manager.package_manager['system'] == 'scoop': print("15. 🍦 Показать bucket'ы Scoop") print("16. 🍦 Добавить bucket Scoop") print("17. 🍦 Обновить Scoop") print("18. 📖 О программе") print("19. ❌ Выход") else: print("15. 📖 О программе") print("16. ❌ Выход") print("="*60) max_choice = 19 if manager.package_manager['system'] == 'scoop' else 16 choice = input(f"Выберите действие (1-{max_choice}): ").strip() if choice == '1': clear_screen() print("📥 Установка Python библиотеки") print("="*30) lib_name = input("Введите название библиотеки: ").strip() version = input("Введите версию (или Enter для последней): ").strip() version = version if version else None manager.install_library(lib_name, version) wait_for_enter() elif choice == '2': clear_screen() print("🖥️ Установка системного пакета") print("="*30) if manager.package_manager['system']: pkg_name = input("Введите название системного пакета: ").strip() manager.install_system_package(pkg_name) else: print("❌ Системный менеджер пакетов не обнаружен") wait_for_enter() elif choice == '3': clear_screen() print("📦 Установка нескольких библиотек") print("="*30) libs_input = input("Введите названия библиотек через пробел: ").strip() libraries = libs_input.split() if libraries: manager.install_multiple_libraries(libraries) else: print("❌ Не указаны библиотеки") wait_for_enter() elif choice == '4': clear_screen() print("🗑️ Удаление библиотеки") print("="*30) lib_name = input("Введите название библиотеки для удаления: ").strip() manager.uninstall_library(lib_name) wait_for_enter() elif choice == '5': clear_screen() print("🔄 Обновление библиотеки") print("="*30) lib_name = input("Введите название библиотеки для обновления: ").strip() manager.update_library(lib_name) wait_for_enter() elif choice == '6': clear_screen() print("🚀 Обновление ВСЕХ библиотек") print("="*30) manager.update_all_libraries() wait_for_enter() elif choice == '7': clear_screen() print("📋 Список установленных библиотек") print("="*40) manager.list_installed() wait_for_enter() elif choice == '8': clear_screen() print("🔍 Поиск библиотек") print("="*30) query = input("Введите запрос для поиска: ").strip() results = manager.search_library(query) if results: print(f"\n🔍 Найдено {len(results)} библиотек:") for lib in results[:10]: print(f" • {lib['name']} - {lib['description']}") else: print("📭 Ничего не найдено") wait_for_enter() elif choice == '9': clear_screen() print("📈 Поиск устаревших библиотек") print("="*30) outdated = manager.find_outdated() if outdated: print(f"🔄 Найдено {len(outdated)} устаревших библиотек:\n") for lib in outdated: print(f" • {lib['name']}: {lib['version']} → {lib['latest_version']}") else: print("✅ Все библиотеки актуальны!") wait_for_enter() elif choice == '10': clear_screen() print("💾 Сохранение зависимостей") print("="*30) manager.save_requirements() wait_for_enter() elif choice == '11': clear_screen() print("📤 Установка из requirements.txt") print("="*30) manager.install_from_requirements() wait_for_enter() elif choice == '12': clear_screen() print("ℹ️ Информация о библиотеке") print("="*30) lib_name = input("Введите название библиотеки: ").strip() info = manager.check_library_info(lib_name) if info: status = "✅ Установлена" if info['installed'] else "❌ Не установлена" print(f"\n📖 Информация о {lib_name}:") print(f" Статус: {status}") print(f" Версия: {info.get('version', 'неизвестно')}") if 'description' in info: print(f" Описание: {info['description']}") else: print(f"❌ Библиотека {lib_name} не найдена") wait_for_enter() elif choice == '13': clear_screen() print("🌐 Открытие страницы на PyPI") print("="*30) lib_name = input("Введите название библиотеки: ").strip() manager.open_pypi_page(lib_name) wait_for_enter() elif choice == '14': clear_screen() print("🧹 Очистка кэш pip") print("="*30) manager.cleanup_cache() wait_for_enter() # Дополнительные опции для Scoop elif choice == '15' and manager.package_manager['system'] == 'scoop': clear_screen() print("🍦 Bucket'ы Scoop") print("="*30) manager.show_scoop_buckets() wait_for_enter() elif choice == '16' and manager.package_manager['system'] == 'scoop': clear_screen() print("🍦 Добавление bucket'а Scoop") print("="*30) bucket_name = input("Введите название bucket'а: ").strip() manager.add_scoop_bucket(bucket_name) wait_for_enter() elif choice == '17' and manager.package_manager['system'] == 'scoop': clear_screen() print("🍦 Обновление Scoop") print("="*30) manager.update_scoop() wait_for_enter() # Меню "О программе" для всех систем elif choice in ['15', '18'] or (choice == '15' and manager.package_manager['system'] != 'scoop'): clear_screen() manager.show_about() wait_for_enter() elif choice in ['16', '19'] or (choice == '16' and manager.package_manager['system'] != 'scoop'): clear_screen() print("👋 До свидания!") print("🐍 Спасибо за использование менеджера библиотек!") break else: print("❌ Неверный выбор. Попробуйте снова.") wait_for_enter() if __name__ == "__main__": main()