127 lines
3.7 KiB
Python
127 lines
3.7 KiB
Python
"""
|
||
故事提取工具 - 入口脚本
|
||
支持开发模式和 PyInstaller 打包模式
|
||
"""
|
||
import os
|
||
import sys
|
||
import shutil
|
||
import socket
|
||
import webbrowser
|
||
import threading
|
||
import time
|
||
|
||
|
||
def get_base_dir() -> str:
|
||
"""获取基础目录"""
|
||
if getattr(sys, 'frozen', False):
|
||
return os.path.dirname(sys.executable)
|
||
else:
|
||
return os.path.dirname(os.path.abspath(__file__))
|
||
|
||
|
||
def cleanup_data(base_dir: str):
|
||
"""启动时清理数据库缓存和临时文件"""
|
||
print("正在清理上次运行的数据...")
|
||
|
||
# 实际数据目录(开发模式下在 backend/ 下,打包后在 exe 同级目录下)
|
||
if getattr(sys, 'frozen', False):
|
||
data_dir = base_dir
|
||
else:
|
||
data_dir = os.path.join(base_dir, "backend")
|
||
|
||
# 清理数据库
|
||
db_dir = os.path.join(data_dir, "data")
|
||
if os.path.exists(db_dir):
|
||
for f in os.listdir(db_dir):
|
||
if f.endswith((".db", ".db-wal", ".db-shm", ".db-journal")):
|
||
try:
|
||
os.remove(os.path.join(db_dir, f))
|
||
except Exception:
|
||
pass
|
||
|
||
# 清理上传的文件
|
||
uploads_dir = os.path.join(data_dir, "uploads")
|
||
if os.path.exists(uploads_dir):
|
||
for subdir in ["transcripts", "persons", "photos"]:
|
||
sub = os.path.join(uploads_dir, subdir)
|
||
if os.path.exists(sub):
|
||
shutil.rmtree(sub, ignore_errors=True)
|
||
|
||
# 清理导出文件
|
||
exports_dir = os.path.join(data_dir, "exports")
|
||
if os.path.exists(exports_dir):
|
||
shutil.rmtree(exports_dir, ignore_errors=True)
|
||
|
||
# 重新创建目录结构
|
||
for d in [db_dir, uploads_dir, exports_dir]:
|
||
os.makedirs(d, exist_ok=True)
|
||
for sub in ["transcripts", "persons", "photos"]:
|
||
os.makedirs(os.path.join(uploads_dir, sub), exist_ok=True)
|
||
|
||
print("清理完成!")
|
||
|
||
|
||
def find_free_port(start_port: int = 8000) -> int:
|
||
"""找到一个可用端口"""
|
||
for port in range(start_port, start_port + 100):
|
||
try:
|
||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||
s.bind(("127.0.0.1", port))
|
||
return port
|
||
except OSError:
|
||
continue
|
||
return start_port
|
||
|
||
|
||
def open_browser(port: int):
|
||
"""延迟打开浏览器"""
|
||
time.sleep(2)
|
||
url = f"http://localhost:{port}"
|
||
print(f"\n正在打开浏览器: {url}")
|
||
webbrowser.open(url)
|
||
|
||
|
||
def main():
|
||
base_dir = get_base_dir()
|
||
|
||
# 1. 清理数据
|
||
cleanup_data(base_dir)
|
||
|
||
# 2. 找可用端口
|
||
port = find_free_port(8000)
|
||
if port != 8000:
|
||
print(f"端口 8000 被占用,使用端口 {port}")
|
||
|
||
# 3. 启动服务
|
||
print(f"\n{'='*50}")
|
||
print(f" 故事提取工具")
|
||
print(f" 访问地址: http://localhost:{port}")
|
||
print(f" 按 Ctrl+C 停止服务")
|
||
print(f"{'='*50}\n")
|
||
|
||
# 延迟打开浏览器(不阻塞主线程)
|
||
threading.Thread(target=open_browser, args=(port,), daemon=True).start()
|
||
|
||
# 启动 uvicorn
|
||
os.environ["APP_PORT"] = str(port)
|
||
|
||
if getattr(sys, 'frozen', False):
|
||
# 打包模式:直接 import 并运行
|
||
import uvicorn
|
||
# 把 backend 目录加到 path,让 app 包能被找到
|
||
backend_dir = os.path.join(base_dir, "backend")
|
||
if backend_dir not in sys.path:
|
||
sys.path.insert(0, backend_dir)
|
||
uvicorn.run("app.main:app", host="0.0.0.0", port=port, log_level="info")
|
||
else:
|
||
# 开发模式
|
||
import uvicorn
|
||
backend_dir = os.path.join(base_dir, "backend")
|
||
if backend_dir not in sys.path:
|
||
sys.path.insert(0, backend_dir)
|
||
uvicorn.run("app.main:app", host="0.0.0.0", port=port, log_level="info")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|