53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""启动本地静态服务并自动选择可用端口。"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import socket
|
||
|
|
import sys
|
||
|
|
import webbrowser
|
||
|
|
from functools import partial
|
||
|
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
ROOT = Path(__file__).resolve().parents[1]
|
||
|
|
|
||
|
|
|
||
|
|
def available_port(start: int) -> int:
|
||
|
|
for port in range(start, start + 20):
|
||
|
|
with socket.socket() as probe:
|
||
|
|
try:
|
||
|
|
probe.bind(("127.0.0.1", port))
|
||
|
|
return port
|
||
|
|
except OSError:
|
||
|
|
continue
|
||
|
|
raise RuntimeError("8765 至 8784 均被占用")
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
parser = argparse.ArgumentParser(description="启动三笙AI情报局本地站点")
|
||
|
|
parser.add_argument("--port", type=int, default=8765)
|
||
|
|
args = parser.parse_args()
|
||
|
|
try:
|
||
|
|
if not (ROOT / "dist" / "index.html").is_file():
|
||
|
|
raise FileNotFoundError("dist/index.html 不存在,请先运行 update.bat")
|
||
|
|
port = available_port(args.port)
|
||
|
|
handler = partial(SimpleHTTPRequestHandler, directory=str(ROOT / "dist"))
|
||
|
|
server = ThreadingHTTPServer(("127.0.0.1", port), handler)
|
||
|
|
url = f"http://127.0.0.1:{port}/"
|
||
|
|
print(f"[启动成功] {url}")
|
||
|
|
webbrowser.open(url)
|
||
|
|
server.serve_forever()
|
||
|
|
except KeyboardInterrupt:
|
||
|
|
print("\n[已停止] 本地服务已关闭")
|
||
|
|
return 0
|
||
|
|
except Exception as exc:
|
||
|
|
print(f"[启动失败] {exc}", file=sys.stderr)
|
||
|
|
return 1
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|