mxivideo/scripts/setup_embedded_python.py

287 lines
8.5 KiB
Python

#!/usr/bin/env python3
"""
设置嵌入式Python环境
下载Python嵌入式版本并配置依赖
"""
import os
import sys
import urllib.request
import zipfile
import subprocess
import shutil
from pathlib import Path
def get_project_root():
"""获取项目根目录"""
return Path(__file__).parent.parent
def download_embedded_python(project_root):
"""下载Python嵌入式版本"""
print("📦 Downloading Python embedded version...")
# Python 3.11.0 嵌入式版本
python_url = "https://www.python.org/ftp/python/3.11.0/python-3.11.0-embed-amd64.zip"
embed_dir = project_root / "src-tauri" / "python-embed"
zip_file = embed_dir / "python-embed.zip"
# 创建目录
embed_dir.mkdir(parents=True, exist_ok=True)
# 下载文件
if not zip_file.exists():
print(f"Downloading from {python_url}...")
urllib.request.urlretrieve(python_url, zip_file)
print("✅ Download completed")
else:
print("✅ Python embed zip already exists")
# 解压文件
print("📂 Extracting Python...")
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
zip_ref.extractall(embed_dir)
# 删除zip文件
zip_file.unlink()
return embed_dir
def setup_pip(embed_dir):
"""设置pip"""
print("🔧 Setting up pip...")
python_exe = embed_dir / "python.exe"
# 下载get-pip.py
get_pip_url = "https://bootstrap.pypa.io/get-pip.py"
get_pip_file = embed_dir / "get-pip.py"
if not get_pip_file.exists():
print("Downloading get-pip.py...")
urllib.request.urlretrieve(get_pip_url, get_pip_file)
# 修改python311._pth文件以启用site-packages
pth_file = embed_dir / "python311._pth"
if pth_file.exists():
content = pth_file.read_text()
if "#import site" in content:
content = content.replace("#import site", "import site")
pth_file.write_text(content)
print("✅ Enabled site-packages")
# 安装pip
try:
result = subprocess.run([
str(python_exe), str(get_pip_file)
], capture_output=True, text=True, cwd=embed_dir)
if result.returncode == 0:
print("✅ pip installed successfully")
else:
print(f"❌ pip installation failed: {result.stderr}")
return False
except Exception as e:
print(f"❌ Error installing pip: {e}")
return False
return True
def install_dependencies(embed_dir):
"""安装Python依赖"""
print("📦 Installing Python dependencies...")
python_exe = embed_dir / "python.exe"
# 基础依赖
dependencies = [
"requests",
"Pillow",
"certifi",
"urllib3",
"charset-normalizer",
"idna",
# 如果需要其他依赖,在这里添加
# "numpy",
# "opencv-python-headless",
# "pandas",
]
for dep in dependencies:
print(f"Installing {dep}...")
try:
result = subprocess.run([
str(python_exe), "-m", "pip", "install", dep
], capture_output=True, text=True, cwd=embed_dir)
if result.returncode == 0:
print(f"{dep} installed")
else:
print(f"❌ Failed to install {dep}: {result.stderr}")
except Exception as e:
print(f"❌ Error installing {dep}: {e}")
def copy_python_core(project_root, embed_dir):
"""复制python_core模块到嵌入式Python"""
print("📋 Copying python_core module...")
source_dir = project_root / "python_core"
target_dir = embed_dir / "python_core"
if source_dir.exists():
if target_dir.exists():
shutil.rmtree(target_dir)
shutil.copytree(source_dir, target_dir)
print("✅ python_core module copied")
else:
print("❌ python_core directory not found")
def create_launcher_script(embed_dir):
"""创建启动脚本"""
print("📝 Creating launcher script...")
launcher_content = '''@echo off
REM Python Core Launcher Script
set PYTHON_DIR=%~dp0
set PYTHONPATH=%PYTHON_DIR%;%PYTHON_DIR%\\python_core
"%PYTHON_DIR%\\python.exe" -m python_core.main %*
'''
launcher_file = embed_dir / "python-core.bat"
launcher_file.write_text(launcher_content)
print("✅ Launcher script created")
def test_embedded_python(embed_dir):
"""测试嵌入式Python"""
print("🧪 Testing embedded Python...")
python_exe = embed_dir / "python.exe"
# 测试Python版本
try:
result = subprocess.run([
str(python_exe), "--version"
], capture_output=True, text=True)
if result.returncode == 0:
print(f"✅ Python version: {result.stdout.strip()}")
else:
print(f"❌ Python test failed: {result.stderr}")
return False
except Exception as e:
print(f"❌ Error testing Python: {e}")
return False
# 测试依赖
test_imports = ["requests", "PIL", "json"]
for module in test_imports:
try:
result = subprocess.run([
str(python_exe), "-c", f"import {module}; print('{module} OK')"
], capture_output=True, text=True)
if result.returncode == 0:
print(f"{module}: {result.stdout.strip()}")
else:
print(f"{module} test failed: {result.stderr}")
except Exception as e:
print(f"❌ Error testing {module}: {e}")
# 测试python_core模块
try:
result = subprocess.run([
str(python_exe), "-c", "import python_core; print('python_core OK')"
], capture_output=True, text=True, cwd=embed_dir)
if result.returncode == 0:
print(f"✅ python_core: {result.stdout.strip()}")
else:
print(f"❌ python_core test failed: {result.stderr}")
except Exception as e:
print(f"❌ Error testing python_core: {e}")
return True
def update_tauri_config(project_root, embed_dir):
"""更新Tauri配置"""
print("⚙️ Updating Tauri configuration...")
import json
config_file = project_root / "src-tauri" / "tauri.conf.json"
if config_file.exists():
with open(config_file, 'r', encoding='utf-8') as f:
config = json.load(f)
# 添加Python嵌入式目录到资源
if 'bundle' not in config:
config['bundle'] = {}
if 'resources' not in config['bundle']:
config['bundle']['resources'] = []
python_resource = "python-embed/**"
if python_resource not in config['bundle']['resources']:
config['bundle']['resources'].append(python_resource)
# 写回配置
with open(config_file, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
print("✅ Tauri configuration updated")
else:
print("❌ Tauri config file not found")
def main():
"""主函数"""
print("🚀 Setting up embedded Python for MixVideo V2...")
print("=" * 50)
project_root = get_project_root()
print(f"Project root: {project_root}")
try:
# 1. 下载嵌入式Python
embed_dir = download_embedded_python(project_root)
# 2. 设置pip
if not setup_pip(embed_dir):
print("❌ Failed to setup pip")
return 1
# 3. 安装依赖
install_dependencies(embed_dir)
# 4. 复制python_core模块
copy_python_core(project_root, embed_dir)
# 5. 创建启动脚本
create_launcher_script(embed_dir)
# 6. 测试
if not test_embedded_python(embed_dir):
print("❌ Embedded Python test failed")
return 1
# 7. 更新Tauri配置
update_tauri_config(project_root, embed_dir)
print("\n🎉 Embedded Python setup completed successfully!")
print(f"📁 Python location: {embed_dir}")
print("\n📋 Next steps:")
print("1. Test the embedded Python:")
print(f" {embed_dir}\\python.exe --version")
print("2. Build your Tauri app:")
print(" cargo tauri build")
print("3. The Python environment will be bundled with your app")
return 0
except Exception as e:
print(f"❌ Setup failed: {e}")
return 1
if __name__ == "__main__":
sys.exit(main())