Global
Exit - 主动退出与生命周期
Exit() 是框架提供的主动退出方法。小写的 exit() 是用户定义的清理回调,与 init()、main() 同级,不能混用。
主动退出
python
Exit()
Exit(reason="达到目标,停止策略")
Exit(code=1, reason="初始化失败")| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
code | int | 0 | 退出码;0 表示正常停止,1–255 表示异常退出,不接受布尔值 |
reason | str | "策略主动退出" | 退出原因,记录到日志并随最终状态上报 |
正常运行期间,调用 Exit() 会中断当前调用栈,不继续执行后面的策略代码。它不会被普通的 except Exception 捕获。不要捕获并吞掉 SystemExit 或 BaseException,否则可能阻止退出。
工作线程也可以调用 Exit():该线程退出,同时通知策略主线程进入清理流程。主线程在取消检查点响应请求,并非强制终止所有工作线程。
生命周期顺序
text
加载并校验策略
↓
init():可选,初始化
↓
main():必需,策略主逻辑
↓
exit():可选,退出清理,只执行一次
↓
进程结束 → 托管端释放资源 → 上报最终状态三个回调均为无参数的同步函数。init() 中退出或发生未处理异常时,跳过 main(),仍调用 exit()。因此清理函数必须兼容只完成部分初始化的情况。
| 情况 | 清理行为 | 最终状态 |
|---|---|---|
main() 正常返回 | 执行 exit() | STOPPED |
Exit() / Exit(code=0) | 先展开调用栈,再执行 exit() | STOPPED |
Exit(code=1) 等非零退出码 | 执行 exit() | ERROR |
| 用户点击停止 | 主逻辑响应停止请求,等待 exit() 完成 | 清理成功后 STOPPED |
未处理异常逃逸出 init() / main() | 记录异常并执行 exit() | ERROR |
exit() 自身抛出异常 | 记录清理失败,不重试回调 | ERROR |
| 脚本无法加载或回调校验失败 | 生命周期尚未建立,不调用 exit() | ERROR |
加载阶段直接调用 Exit() 会结束加载并上报退出码、原因,但尚未建立清理回调。需要清理的初始化逻辑应放在 init() 内,而非模块顶层。
策略自身已有的 try/finally 先执行,随后框架调用 exit();同一资源的关闭操作应幂等,或只放在一个位置。已有主循环的异常日志/继续运行机制不变:被捕获的异常不会自动结束策略。
停止与等待
- Python 的正常停止通过托管端控制通道请求退出,不直接杀进程。
- 清理期间仍保留交易接口、日志与状态服务,允许
exit()撤单、保存数据、关闭连接。 - 没有原先的 5 秒强杀超时。 如果
exit()一直不返回,正常停止就一直等待;不会提前上报STOPPED。 - 重复停止不会重入回调。在退出清理期间再次调用
Exit()不会打断清理,也不会覆盖第一次退出请求。 - Python 策略的
while/for循环及Sleep()包含协作式取消检查。正在执行的第三方阻塞调用需要先返回;请设置网络、线程等待等操作的超时,避免无限阻塞。 exit()内的Sleep()仍按正常时长等待,不会因停止标记而跳过。- 用户创建的线程和连接应由清理回调主动停止、关闭并等待完成。框架不会安全地“强杀”某个 Python 工作线程。
- 系统强杀、崩溃、断电等不可恢复事件无法保证回调执行;不要使用
os._exit()绕过清理。
最终状态由托管端在策略进程实际结束、资源清理后,通过已有状态上报通道发送。成功退出使用 STOPPED,不新增服务器状态枚举;非零退出或清理失败使用 ERROR。退出原因和退出码放入状态消息。网络不可用时会明确记录上报失败,不把日志输出等同于服务器已收到。
完整示例
python
ws = None
def init():
global ws
ws = Dial("wss://fstream.binance.com/ws/btcusdt@depth",
timeout=10000, auto_reconnect=True)
if ws is None:
Exit(code=1, reason="行情连接失败")
Log("初始化完成")
def main():
while True:
command = GetCommand()
if command == "stop":
Exit(reason="收到停止指令")
message = ws.read(250)
if message:
LogStatus(message)
Sleep(100)
def exit():
global ws
Log("开始清理")
try:
_G("last_exit_time", Unix())
finally:
if ws is not None:
ws.close()
ws = None
Log("清理完成")旧接口迁移
原先注入的 exit(reason) 主动停止方法已移除,不再调用废弃的停止管理接口。
python
# 旧调用 exit("达到目标") 应改成:
Exit(reason="达到目标")
# 清理逻辑定义为小写 exit,由框架调用:
def exit():
Log("退出清理")不要直接调用小写 exit() 来请求停止;它只是你的普通清理函数。已有仅定义 init() / main() 的策略仍可运行,不强制要求新增清理回调。
相关方法
- Dial - 网络连接
- Sleep - 可响应停止请求的休眠
- GetCommand - 获取交互指令