This commit is contained in:
2025-10-07 17:03:14 +08:00
parent 8a4fec28cf
commit 22d4a9057b
13 changed files with 873 additions and 1 deletions

173
dev.py Normal file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/env python
"""
WebSocket 开发服务器启动脚本
同时启动 Daphne (WebSocket) 和 Django runserver (开发服务器)
支持 Windows 和 Linux
"""
import os
import sys
import subprocess
import platform
import signal
from pathlib import Path
from threading import Thread
import time
def main():
# 获取项目根目录
base_dir = Path(__file__).resolve().parent
os.chdir(base_dir)
print("=" * 70)
print("启动 Django 开发服务器 + WebSocket 服务器")
print("=" * 70)
print()
# 检测操作系统
is_windows = platform.system() == "Windows"
# 检查虚拟环境(跨平台)
if is_windows:
# Windows: .venv/Scripts/python.exe
venv_python = base_dir / ".venv" / "Scripts" / "python.exe"
else:
# Linux/Mac: .venv/bin/python
venv_python = base_dir / ".venv" / "bin" / "python"
if venv_python.exists():
print("[✓] 使用虚拟环境: .venv")
python_exec = str(venv_python)
else:
print("[!] 未找到 .venv 虚拟环境,使用全局 Python")
print("[!] 建议创建虚拟环境: python -m venv .venv")
python_exec = sys.executable
# 检查 daphne 是否安装
try:
result = subprocess.run(
[python_exec, "-m", "daphne", "--version"], capture_output=True, text=True
)
if result.returncode != 0 and result.returncode != 2:
print("[✗] 错误: Daphne 未安装")
print("请运行: pip install daphne channels channels-redis")
sys.exit(1)
except FileNotFoundError:
print("[✗] 错误: 无法找到 Python 解释器")
sys.exit(1)
# 进程列表
processes = []
# 启动两个服务器
try:
# 启动 Django runserver (端口 8000)
print("[*] 启动 Django 开发服务器 (端口 8000)...")
runserver_cmd = ["uv", "run", "manage.py", "runserver", "0.0.0.0:8000"]
runserver_process = subprocess.Popen(
runserver_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True,
)
processes.append(("Django Runserver", runserver_process))
# 等待一下,让 runserver 先启动
time.sleep(1)
# 启动 Daphne (端口 8001)
print("[*] 启动 Daphne WebSocket 服务器 (端口 8001)...")
daphne_cmd = [
python_exec,
"-m",
"daphne",
"-b",
"0.0.0.0",
"-p",
"8001",
"oj.asgi:application",
]
daphne_process = subprocess.Popen(
daphne_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True,
)
processes.append(("Daphne", daphne_process))
print()
print("[✓] 所有服务器已启动")
print()
# 创建输出线程
def print_output(name, process):
"""打印进程输出"""
for line in process.stdout:
print(f"[{name}] {line}", end="")
# 启动输出线程
threads = []
for name, process in processes:
thread = Thread(target=print_output, args=(name, process), daemon=True)
thread.start()
threads.append(thread)
# 等待进程(任意一个退出就退出)
while True:
for name, process in processes:
if process.poll() is not None:
print(f"\n[!] {name} 已退出")
raise KeyboardInterrupt
time.sleep(0.5)
except KeyboardInterrupt:
print()
print()
print("[*] 正在停止所有服务器...")
# 终止所有进程
for name, process in processes:
try:
if process.poll() is None: # 如果进程还在运行
print(f"[*] 停止 {name}...")
if is_windows:
# Windows 使用 CTRL_C_EVENT
process.send_signal(signal.CTRL_C_EVENT)
else:
# Unix 使用 SIGTERM
process.terminate()
# 等待进程结束(最多 5 秒)
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
print(f"[!] {name} 未响应,强制终止...")
process.kill()
process.wait()
except Exception as e:
print(f"[!] 停止 {name} 时出错: {e}")
print()
print("[✓] 所有服务器已停止")
except Exception as e:
print(f"[✗] 错误: {e}")
# 清理所有进程
for name, process in processes:
try:
if process.poll() is None:
process.kill()
process.wait()
except Exception:
pass
sys.exit(1)
if __name__ == "__main__":
main()