287 lines
8.5 KiB
Python
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())
|