296 lines
10 KiB
Python
296 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
JakeUpgrade Nodes Auto-Install Script
|
|
JakeUpgrade 节点自动安装脚本
|
|
用于安装 ComfyUI 自定义节点所需的依赖包
|
|
For installing dependencies required by ComfyUI custom nodes
|
|
"""
|
|
|
|
import sys
|
|
import subprocess
|
|
import os
|
|
import platform
|
|
import re
|
|
from pathlib import Path
|
|
|
|
def get_comfyui_path():
|
|
"""获取 ComfyUI 根目录路径 / Get ComfyUI root path"""
|
|
current_dir = Path(__file__).parent
|
|
|
|
# 尝试多种可能的目录结构
|
|
possible_paths = [
|
|
current_dir.parent.parent, # root\ComfyUI\custom_nodes\
|
|
current_dir.parent.parent.parent, # root\ComfyUI\custom_nodes\node_name
|
|
current_dir.parent.parent.parent.parent, # root\ComfyUI\custom_nodes\node_name\subfolder
|
|
]
|
|
|
|
for comfy_path in possible_paths:
|
|
# 检查是否是 ComfyUI 目录
|
|
if (comfy_path / "ComfyUI").exists():
|
|
return comfy_path
|
|
|
|
# 如果找不到,返回当前目录的父目录的父目录
|
|
return current_dir.parent.parent
|
|
|
|
def get_python_executable():
|
|
"""获取 Python 可执行文件路径 / Get Python executable path"""
|
|
comfy_path = get_comfyui_path()
|
|
|
|
# 优先使用嵌入式 Python / Prefer embedded Python
|
|
embedded_python = comfy_path / "python_embeded" / "python.exe"
|
|
if embedded_python.exists():
|
|
print(f"✅ Using embedded Python: {embedded_python}")
|
|
return str(embedded_python)
|
|
|
|
# 检查 ComfyUI 目录下的嵌入式 Python
|
|
embedded_python2 = comfy_path / "ComfyUI" / "python_embeded" / "python.exe"
|
|
if embedded_python2.exists():
|
|
print(f"✅ Using embedded Python: {embedded_python2}")
|
|
return str(embedded_python2)
|
|
|
|
# 使用系统 Python / Use system Python
|
|
system_python = sys.executable
|
|
print(f"✅ Using system Python: {system_python}")
|
|
return system_python
|
|
|
|
def check_python_version(python_exec):
|
|
"""检查 Python 版本 / Check Python version"""
|
|
print("🔍 Checking Python version...")
|
|
try:
|
|
result = subprocess.run(
|
|
[python_exec, "--version"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10
|
|
)
|
|
if result.returncode == 0:
|
|
version_output = result.stdout.strip()
|
|
print(f"✅ Python version: {version_output}")
|
|
|
|
# 解析版本号 / Parse version number
|
|
version_match = re.search(r"Python (\d+)\.(\d+)", version_output)
|
|
if version_match:
|
|
major, minor = int(version_match.group(1)), int(version_match.group(2))
|
|
if major < 3 or (major == 3 and minor < 8):
|
|
print(f"❌ Unsupported Python version: {version_output}")
|
|
print("✅ Requires Python 3.8 or higher")
|
|
return False
|
|
return True
|
|
except Exception as e:
|
|
print(f"❌ Failed to check Python version: {e}")
|
|
return False
|
|
|
|
return True
|
|
|
|
def check_existing_dependencies(python_exec):
|
|
"""检查已安装的依赖 / Check existing dependencies"""
|
|
print("\n🔍 Checking existing dependencies...")
|
|
|
|
try:
|
|
# 获取已安装的包列表
|
|
result = subprocess.run(
|
|
[python_exec, "-s", "-m", "pip", "list", "--format=freeze"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
installed_packages = set()
|
|
for line in result.stdout.strip().split('\n'):
|
|
if line and '==' in line:
|
|
pkg = line.split('==', 1)[0].strip().lower()
|
|
installed_packages.add(pkg)
|
|
|
|
# 读取 requirements.txt
|
|
current_dir = Path(__file__).parent
|
|
requirements_file = current_dir / "requirements.txt"
|
|
|
|
with open(requirements_file, 'r', encoding='utf-8') as f:
|
|
requirements = f.readlines()
|
|
|
|
missing_packages = []
|
|
for req in requirements:
|
|
req = req.strip()
|
|
if not req or req.startswith('#'):
|
|
continue
|
|
|
|
# 只检查包名,不考虑版本
|
|
pkg_name = req.strip().lower()
|
|
|
|
if pkg_name not in installed_packages:
|
|
missing_packages.append(req)
|
|
print(f"❌ {req} - Not installed")
|
|
else:
|
|
print(f"✅ {req} - Already installed")
|
|
|
|
return missing_packages
|
|
else:
|
|
print(f"❌ Cannot get installed packages: {result.stderr}")
|
|
return None
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error checking dependencies: {e}")
|
|
return None
|
|
|
|
def install_missing_only(python_exec, missing_packages):
|
|
"""只安装缺失的包 / Install only missing packages"""
|
|
if not missing_packages:
|
|
print("✅ All dependencies already installed")
|
|
return True
|
|
|
|
print(f"\n📦 Packages to install: {', '.join(missing_packages)}")
|
|
|
|
try:
|
|
# 为所有缺失的包一次性安装
|
|
print("⏳ Installing missing dependencies...")
|
|
result = subprocess.run(
|
|
[python_exec, "-s", "-m", "pip", "install"] + missing_packages,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=300
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
print("✅ Missing dependencies installed")
|
|
return True
|
|
else:
|
|
print(f"❌ Installation failed: {result.stderr}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Exception during installation: {e}")
|
|
return False
|
|
|
|
def install_requirements(python_exec):
|
|
"""安装 requirements.txt 中的依赖 / Install dependencies from requirements.txt"""
|
|
print("\n📦 Starting dependency check...")
|
|
|
|
current_dir = Path(__file__).parent
|
|
requirements_file = current_dir / "requirements.txt"
|
|
|
|
if not requirements_file.exists():
|
|
print(f"❌ requirements.txt not found: {requirements_file}")
|
|
return False
|
|
|
|
try:
|
|
# 首先检查已安装的依赖
|
|
missing_packages = check_existing_dependencies(python_exec)
|
|
|
|
if missing_packages is None:
|
|
# 如果检查失败,回退到传统安装方式
|
|
print("⚠️ Dependency check failed, using traditional installation")
|
|
return install_traditional(python_exec, requirements_file)
|
|
|
|
# 只安装缺失的包
|
|
return install_missing_only(python_exec, missing_packages)
|
|
|
|
except Exception as e:
|
|
print(f"❌ Exception during installation: {e}")
|
|
return install_traditional(python_exec, requirements_file)
|
|
|
|
def install_traditional(python_exec, requirements_file):
|
|
"""传统安装方式(备用) / Traditional installation (fallback)"""
|
|
print("🔄 Using traditional installation method")
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
[python_exec, "-s", "-m", "pip", "install", "-r", str(requirements_file)],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=300
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
print("✅ Dependencies installation completed!")
|
|
return True
|
|
else:
|
|
print(f"❌ Error during installation:")
|
|
if result.stdout:
|
|
print(f"Stdout: {result.stdout}")
|
|
if result.stderr:
|
|
print(f"Stderr: {result.stderr}")
|
|
return False
|
|
|
|
except subprocess.TimeoutExpired:
|
|
print("❌ Installation timeout, check network connection or install manually")
|
|
return False
|
|
|
|
def check_installation(python_exec):
|
|
"""检查安装结果 / Check installation results"""
|
|
print("\n🔍 Checking installation results...")
|
|
|
|
packages_to_check = [
|
|
("cv2", "opencv-python"),
|
|
("piexif", "piexif"),
|
|
("torch", "torch"),
|
|
("torchvision", "torchvision"),
|
|
("numpy", "numpy"),
|
|
("PIL", "pillow"),
|
|
("simpleeval", "simpleeval"),
|
|
("functools", "functools"),
|
|
("yaml", "PyYAML"),
|
|
("toml", "toml"),
|
|
|
|
]
|
|
|
|
all_installed = True
|
|
for import_name, package_name in packages_to_check:
|
|
try:
|
|
# 使用指定的 Python 执行器检查
|
|
check_script = f"import {import_name}" if import_name != "PIL" else "import PIL"
|
|
result = subprocess.run(
|
|
[python_exec, "-c", check_script],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10
|
|
)
|
|
if result.returncode == 0:
|
|
print(f"✅ {package_name} installed correctly")
|
|
else:
|
|
print(f"❌ {package_name} installation failed: {result.stderr}")
|
|
all_installed = False
|
|
except Exception as e:
|
|
print(f"❌ Error checking {package_name}: {e}")
|
|
all_installed = False
|
|
|
|
return all_installed
|
|
|
|
def main():
|
|
"""主函数 / Main function"""
|
|
print("=" * 60)
|
|
print("🛠️ JakeUpgrade Nodes Installer")
|
|
print("=" * 60)
|
|
|
|
# 检查系统信息
|
|
print(f"💻 OS: {platform.system()} {platform.release()}")
|
|
print(f"📁 Working directory: {Path(__file__).parent}")
|
|
|
|
# 获取 Python 执行器
|
|
python_exec = get_python_executable()
|
|
|
|
# 执行安装步骤
|
|
if not check_python_version(python_exec):
|
|
sys.exit(1)
|
|
|
|
if not install_requirements(python_exec):
|
|
print("\n❌ Dependency installation failed, try manual installation:")
|
|
print(" 1. Open command prompt or terminal")
|
|
print(" 2. Change to current directory")
|
|
print(f" 3. Run: {python_exec} -m pip install -r requirements.txt")
|
|
sys.exit(1)
|
|
|
|
# 验证安装
|
|
if check_installation(python_exec):
|
|
print("\n🎉 Installation complete! JakeUpgrade Nodes ready!")
|
|
print("🔧 You can now start ComfyUI and use JakeUpgrade nodes")
|
|
else:
|
|
print("\n⚠️ Some dependencies may not be installed correctly")
|
|
print("💡 Recommended to restart ComfyUI and check if nodes work properly")
|
|
|
|
print("\nPress Enter to exit...")
|
|
input()
|
|
|
|
if __name__ == "__main__":
|
|
import re
|
|
main() |