Spaces:
Paused
Paused
File size: 6,691 Bytes
1af767b fe717e9 1af767b d0390eb c0c60d3 d0390eb 1af767b fe717e9 1af767b fe717e9 1af767b fe717e9 1af767b fe717e9 1af767b fe717e9 55a0955 febcb81 55a0955 febcb81 55a0955 2dc82a6 55a0955 2dc82a6 55a0955 2dc82a6 fe717e9 1af767b c0c60d3 2dc82a6 c0c60d3 2dc82a6 1af767b 9285882 1af767b 55a0955 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
"""
Kaggle/Colab 启动脚本
用于启动 FastAPI 服务器并配置 ngrok 穿透
"""
import os
import sys
import subprocess
import time
import threading
import re
import shutil
def install_ngrok(max_retries: int = 3):
"""安装 pyngrok 和 cloudflared(使用国内镜像,失败自动重试)"""
print("🔧 正在安装 Web 穿透工具...")
mirrors = [
"https://pypi.tuna.tsinghua.edu.cn/simple",
"https://mirrors.aliyun.com/pypi/simple",
None, # 退回默认源
]
for attempt in range(1, max_retries + 1):
mirror = mirrors[min(attempt - 1, len(mirrors) - 1)]
cmd = [
sys.executable,
"-m",
"pip",
"install",
"--no-cache-dir",
"--default-timeout",
"120",
]
if mirror:
cmd.extend(["-i", mirror])
cmd.extend(["pyngrok", "cloudflared"])
try:
print(f"⏳ 第 {attempt} 次安装,使用源: {mirror or '默认 PyPI'}")
subprocess.check_call(cmd)
print("✅ 穿透工具安装完成")
return True
except subprocess.CalledProcessError as e:
print(f"⚠️ 安装失败: {e}")
time.sleep(5)
print("❌ 多次尝试后仍无法安装 pyngrok/cloudflared")
return False
def run_server():
"""在后台运行服务器"""
print("🚀 启动 FastAPI 服务器...")
subprocess.Popen([sys.executable, "server.py"])
def start_ngrok():
try:
from pyngrok import ngrok
token = os.environ.get("NGROK_AUTHTOKEN")
if not token:
print("\n⚠️ 警告: 未设置 NGROK_AUTHTOKEN 环境变量")
return False
ngrok.set_auth_token(token)
public_url = ngrok.connect(8000).public_url
print("\n" + "="*60)
print("✅ 成功穿透! 公网访问地址:")
print(f"👉 {public_url}")
print("="*60 + "\n")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
ngrok.kill()
return True
except ImportError:
print("❌ pyngrok 导入失败,请确保已安装")
return False
except Exception as e:
print(f"❌ ngrok 启动失败: {e}")
return False
def start_cloudflared():
try:
cmd = None
# 1. 检查系统路径
if shutil.which("cloudflared"):
cmd = ["cloudflared", "tunnel", "--url", "http://localhost:8000", "--no-autoupdate"]
# 2. 检查当前目录
elif os.path.exists("./cloudflared"):
cmd = ["./cloudflared", "tunnel", "--url", "http://localhost:8000", "--no-autoupdate"]
# 确保有执行权限
try:
os.chmod("./cloudflared", 0o755)
except:
pass
else:
# 如果找不到 cloudflared 二进制,尝试通过 pip 安装的 cloudflared 运行
# 注意:cloudflared 的 pip 包可能不直接暴露 cloudflared 命令
# 我们尝试直接下载二进制文件
print("⚠️ 未找到 cloudflared 命令,尝试下载二进制文件...")
try:
# 这里简化处理,如果 pip 安装的模块无法直接运行,提示用户手动安装
# 或者尝试使用 pyngrok 作为回退
print("⚠️ 无法通过 Python 模块启动 cloudflared,将尝试仅使用 pyngrok")
return
except Exception:
print("⚠️ 未找到 cloudflared,可通过 'pip install cloudflared' 安装,或跳过穿透")
return
if cmd:
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
url = None
while True:
line = proc.stdout.readline()
if not line:
break
if "trycloudflare.com" in line:
m = re.search(r"https?://[\w\.-]+trycloudflare\.com[\S]*", line)
if m:
url = m.group(0)
print("\n" + "="*60)
print("✅ 成功穿透! 公网访问地址:")
print(f"👉 {url}")
print("="*60 + "\n")
break
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
proc.terminate()
except Exception as e:
print(f"❌ Cloudflare Tunnel 启动失败: {e}")
if __name__ == "__main__":
# 1. 安装依赖
try:
import uvicorn
import fastapi
except ImportError:
print("🔧 安装 FastAPI 依赖...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "fastapi", "uvicorn", "python-multipart"])
try:
import pyngrok
except ImportError:
install_ngrok()
# 检查 cloudflared 是否存在,如果不存在尝试安装
if not shutil.which("cloudflared"):
# 尝试作为 Python 模块调用,但先不导入它来检查,而是直接看 pip list 或依赖 subprocess
# 由于 cloudflared 库可能有导入问题,我们这里只做安装尝试,不做导入检查
pass
# 2. 启动 FastAPI
server_thread = threading.Thread(target=run_server)
server_thread.daemon = True
server_thread.start()
# 等待服务器启动 (循环检查端口)
print("⏳ 等待服务器启动...")
import socket
def wait_for_port(port, host='127.0.0.1', timeout=60):
start_time = time.time()
while True:
try:
with socket.create_connection((host, port), timeout=1):
print(f"✅ 服务器已在 {host}:{port} 就绪")
return True
except (OSError, ConnectionRefusedError):
if time.time() - start_time > timeout:
print(f"❌ 服务器启动超时 ({timeout}s)")
return False
time.sleep(1)
if not wait_for_port(8000):
print("❌ 服务器未能成功启动,请检查日志")
sys.exit(1)
use_tunnel = os.environ.get("USE_TUNNEL", "true").lower() == "true"
if use_tunnel:
ok = start_ngrok()
if not ok:
start_cloudflared()
else:
print("\n" + "="*60)
print("✅ 服务器已启动,局域网访问地址:")
print("👉 http://127.0.0.1:8000")
print("="*60 + "\n")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
|