日志展示优化
This commit is contained in:
@@ -755,226 +755,226 @@ class BitmartFuturesTransaction:
|
||||
|
||||
if page_start:
|
||||
# 打开浏览器
|
||||
for i in range(5):
|
||||
if self.openBrowser():
|
||||
logger.info(LOG_SYSTEM + "浏览器打开成功")
|
||||
break
|
||||
else:
|
||||
self.ding("打开浏览器失败!", error=True)
|
||||
return
|
||||
for i in range(5):
|
||||
if self.openBrowser():
|
||||
logger.info(LOG_SYSTEM + "浏览器打开成功")
|
||||
break
|
||||
else:
|
||||
self.ding("打开浏览器失败!", error=True)
|
||||
return
|
||||
|
||||
# 进入交易页面
|
||||
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
# 进入交易页面
|
||||
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
|
||||
self.click_safe('x://button[normalize-space(text()) ="市价"]')
|
||||
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=25, clear=True)
|
||||
self.page.ele('x://*[@id="size_0"]').input(vals=25, clear=True)
|
||||
|
||||
page_start = False
|
||||
page_start = False
|
||||
|
||||
try:
|
||||
# 1. 获取K线数据(当前K线和上一根K线)
|
||||
prev_kline, current_kline = self.get_klines()
|
||||
if not prev_kline or not current_kline:
|
||||
logger.warning(LOG_SYSTEM + "获取K线失败,等待重试...")
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# 记录进入新的K线(分块分隔,便于阅读)
|
||||
current_kline_time = current_kline['id']
|
||||
if self.last_kline_time != current_kline_time:
|
||||
self.last_kline_time = current_kline_time
|
||||
logger.info("")
|
||||
log_kline_header(current_kline_time)
|
||||
|
||||
# 2. 获取当前价格
|
||||
current_price = self.get_current_price()
|
||||
if not current_price:
|
||||
logger.warning(LOG_SYSTEM + "获取价格失败,等待重试...")
|
||||
time.sleep(2)
|
||||
continue
|
||||
|
||||
# 3. 每次循环都通过SDK获取真实持仓状态(避免状态不同步导致双向持仓)
|
||||
if not self.get_position_status():
|
||||
logger.warning(LOG_SYSTEM + "获取持仓状态失败,等待重试...")
|
||||
time.sleep(2)
|
||||
continue
|
||||
|
||||
logger.debug(f"当前持仓状态: {self.start} (0=无, 1=多, -1=空)")
|
||||
|
||||
# 更新仪表盘左侧数据(供 Rich 展示)
|
||||
try:
|
||||
self._display_state["price"] = current_price
|
||||
self._display_state["position"] = self.start
|
||||
self._display_state["kline_id"] = current_kline_time
|
||||
self._display_state["unrealized_pnl"] = self.get_unrealized_pnl_usd()
|
||||
kline_series = self.get_klines_series(35)
|
||||
ema10, ema20, atr14 = self.get_ema_atr_for_exit(kline_series)
|
||||
self._display_state["ema10"] = ema10
|
||||
self._display_state["atr14"] = atr14
|
||||
if getattr(self, "_display_triggers", None):
|
||||
self._display_state.update(self._display_triggers)
|
||||
except Exception:
|
||||
pass
|
||||
# 1. 获取K线数据(当前K线和上一根K线)
|
||||
prev_kline, current_kline = self.get_klines()
|
||||
if not prev_kline or not current_kline:
|
||||
logger.warning(LOG_SYSTEM + "获取K线失败,等待重试...")
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# 3.5 止损/止盈/移动止损 + EMA/ATR 平仓 + 当前K线从极值回落平仓
|
||||
if self.start != 0:
|
||||
# 当前K线从最高/最低点回落平仓:换线重置跟踪,有持仓时更新本K线内最高/最低价并检查
|
||||
if self._candle_id_for_high_low != current_kline_time:
|
||||
self._candle_high_seen = None
|
||||
self._candle_low_seen = None
|
||||
self._candle_id_for_high_low = current_kline_time
|
||||
# 多头:先更新本 K 线最高价(供 ATR 追踪与后续回落逻辑用)
|
||||
if self.start == 1:
|
||||
self._candle_high_seen = max(self._candle_high_seen or 0, current_price)
|
||||
elif self.start == -1:
|
||||
self._candle_low_seen = min(self._candle_low_seen or float('inf'), current_price)
|
||||
# 记录进入新的K线(分块分隔,便于阅读)
|
||||
current_kline_time = current_kline['id']
|
||||
if self.last_kline_time != current_kline_time:
|
||||
self.last_kline_time = current_kline_time
|
||||
logger.info("")
|
||||
log_kline_header(current_kline_time)
|
||||
|
||||
# 多单:EMA(10) + ATR(14) 平仓 —— 收盘跌破 EMA10 先平;或从最高价回撤 ≥ 1.1×ATR 平
|
||||
if self.start == 1 and self.use_ema_atr_exit:
|
||||
# 2. 获取当前价格
|
||||
current_price = self.get_current_price()
|
||||
if not current_price:
|
||||
logger.warning(LOG_SYSTEM + "获取价格失败,等待重试...")
|
||||
time.sleep(2)
|
||||
continue
|
||||
|
||||
# 3. 每次循环都通过SDK获取真实持仓状态(避免状态不同步导致双向持仓)
|
||||
if not self.get_position_status():
|
||||
logger.warning(LOG_SYSTEM + "获取持仓状态失败,等待重试...")
|
||||
time.sleep(2)
|
||||
continue
|
||||
|
||||
logger.debug(f"当前持仓状态: {self.start} (0=无, 1=多, -1=空)")
|
||||
|
||||
# 更新仪表盘左侧数据(供 Rich 展示)
|
||||
try:
|
||||
self._display_state["price"] = current_price
|
||||
self._display_state["position"] = self.start
|
||||
self._display_state["kline_id"] = current_kline_time
|
||||
self._display_state["unrealized_pnl"] = self.get_unrealized_pnl_usd()
|
||||
kline_series = self.get_klines_series(35)
|
||||
ema10, ema20, atr14 = self.get_ema_atr_for_exit(kline_series)
|
||||
if ema10 is not None and current_price < ema10:
|
||||
logger.info(LOG_POSITION + f"多单 EMA10 平仓 | 价 {current_price:.2f} 跌破 EMA10 {ema10:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_high_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
if atr14 is not None and self._candle_high_seen and (self._candle_high_seen - current_price) >= self.atr_multiplier * atr14:
|
||||
logger.info(LOG_POSITION + f"多单 ATR 追踪止盈 | 最高 {self._candle_high_seen:.2f} 当前 {current_price:.2f} 回撤≥{self.atr_multiplier}×ATR={atr14:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_high_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
self._display_state["ema10"] = ema10
|
||||
self._display_state["atr14"] = atr14
|
||||
if getattr(self, "_display_triggers", None):
|
||||
self._display_state.update(self._display_triggers)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 空单:EMA(10) + ATR(14) 平仓 —— 收盘涨破 EMA10 先平;或从最低价反弹 ≥ 1.1×ATR 平
|
||||
if self.start == -1 and self.use_ema_atr_exit:
|
||||
kline_series = self.get_klines_series(35)
|
||||
ema10, ema20, atr14 = self.get_ema_atr_for_exit(kline_series)
|
||||
if ema10 is not None and current_price > ema10:
|
||||
logger.info(LOG_POSITION + f"空单 EMA10 平仓 | 价 {current_price:.2f} 涨破 EMA10 {ema10:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
# 3.5 止损/止盈/移动止损 + EMA/ATR 平仓 + 当前K线从极值回落平仓
|
||||
if self.start != 0:
|
||||
# 当前K线从最高/最低点回落平仓:换线重置跟踪,有持仓时更新本K线内最高/最低价并检查
|
||||
if self._candle_id_for_high_low != current_kline_time:
|
||||
self._candle_high_seen = None
|
||||
self._candle_low_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
if atr14 is not None and self._candle_low_seen and (current_price - self._candle_low_seen) >= self.atr_multiplier * atr14:
|
||||
logger.info(LOG_POSITION + f"空单 ATR 追踪止盈 | 最低 {self._candle_low_seen:.2f} 当前 {current_price:.2f} 反弹≥{self.atr_multiplier}×ATR={atr14:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_low_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
self._candle_id_for_high_low = current_kline_time
|
||||
# 多头:先更新本 K 线最高价(供 ATR 追踪与后续回落逻辑用)
|
||||
if self.start == 1:
|
||||
self._candle_high_seen = max(self._candle_high_seen or 0, current_price)
|
||||
elif self.start == -1:
|
||||
self._candle_low_seen = min(self._candle_low_seen or float('inf'), current_price)
|
||||
|
||||
use_fixed = self.drop_from_high_mode == 'fixed' and self.drop_from_high_to_close and self.drop_from_high_to_close > 0
|
||||
use_pct = self.drop_from_high_mode == 'pct_retrace'
|
||||
if use_fixed or use_pct:
|
||||
if self.start == 1: # 多头:最高价已在上面更新,这里只做回落判断
|
||||
do_close = False
|
||||
if use_fixed and self._candle_high_seen and current_price <= self._candle_high_seen - self.drop_from_high_to_close:
|
||||
do_close = True
|
||||
reason = f"固定回落 {self.drop_from_high_to_close}"
|
||||
elif use_pct and self._candle_high_seen and current_kline.get('open'):
|
||||
candle_open = float(current_kline['open'])
|
||||
rise_pct = (self._candle_high_seen - candle_open) / candle_open * 100 if candle_open > 0 else 0
|
||||
if rise_pct >= self.min_rise_pct_to_activate:
|
||||
drop_trigger_pct = max(self.min_drop_pct_from_high, rise_pct * self.retrace_ratio)
|
||||
drop_pct = (self._candle_high_seen - current_price) / self._candle_high_seen * 100 if self._candle_high_seen else 0
|
||||
if drop_pct >= drop_trigger_pct:
|
||||
do_close = True
|
||||
reason = f"涨幅 {rise_pct:.3f}% → 允许回撤 {drop_trigger_pct:.3f}%,实际回撤 {drop_pct:.3f}%"
|
||||
else:
|
||||
pass # 涨幅不足,不启用动态回撤
|
||||
if do_close:
|
||||
logger.info(LOG_POSITION + f"多单K线回落平仓 | 最高 {self._candle_high_seen:.2f} 当前 {current_price:.2f} | {reason}")
|
||||
# 多单:EMA(10) + ATR(14) 平仓 —— 收盘跌破 EMA10 先平;或从最高价回撤 ≥ 1.1×ATR 平
|
||||
if self.start == 1 and self.use_ema_atr_exit:
|
||||
kline_series = self.get_klines_series(35)
|
||||
ema10, ema20, atr14 = self.get_ema_atr_for_exit(kline_series)
|
||||
if ema10 is not None and current_price < ema10:
|
||||
logger.info(LOG_POSITION + f"多单 EMA10 平仓 | 价 {current_price:.2f} 跌破 EMA10 {ema10:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_high_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
elif self.start == -1: # 空头:跟踪当前K线最低价,从最低点反弹超过阈值则平仓
|
||||
self._candle_low_seen = min(self._candle_low_seen or float('inf'), current_price)
|
||||
do_close = False
|
||||
if use_fixed and self._candle_low_seen and current_price >= self._candle_low_seen + self.drop_from_high_to_close:
|
||||
do_close = True
|
||||
reason = f"固定反弹 {self.drop_from_high_to_close}"
|
||||
elif use_pct and self._candle_low_seen and current_kline.get('open'):
|
||||
candle_open = float(current_kline['open'])
|
||||
rise_pct = (candle_open - self._candle_low_seen) / candle_open * 100 if candle_open > 0 else 0 # 对空头是“跌幅”
|
||||
if rise_pct >= self.min_rise_pct_to_activate:
|
||||
drop_trigger_pct = max(self.min_drop_pct_from_high, rise_pct * self.retrace_ratio)
|
||||
bounce_pct = (current_price - self._candle_low_seen) / self._candle_low_seen * 100 if self._candle_low_seen else 0
|
||||
if bounce_pct >= drop_trigger_pct:
|
||||
do_close = True
|
||||
reason = f"跌幅 {rise_pct:.3f}% → 允许反弹 {drop_trigger_pct:.3f}%,实际反弹 {bounce_pct:.3f}%"
|
||||
if do_close:
|
||||
logger.info(LOG_POSITION + f"空单K线反弹平仓 | 最低 {self._candle_low_seen:.2f} 当前 {current_price:.2f} | {reason}")
|
||||
if atr14 is not None and self._candle_high_seen and (self._candle_high_seen - current_price) >= self.atr_multiplier * atr14:
|
||||
logger.info(LOG_POSITION + f"多单 ATR 追踪止盈 | 最高 {self._candle_high_seen:.2f} 当前 {current_price:.2f} 回撤≥{self.atr_multiplier}×ATR={atr14:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_high_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
# 空单:EMA(10) + ATR(14) 平仓 —— 收盘涨破 EMA10 先平;或从最低价反弹 ≥ 1.1×ATR 平
|
||||
if self.start == -1 and self.use_ema_atr_exit:
|
||||
kline_series = self.get_klines_series(35)
|
||||
ema10, ema20, atr14 = self.get_ema_atr_for_exit(kline_series)
|
||||
if ema10 is not None and current_price > ema10:
|
||||
logger.info(LOG_POSITION + f"空单 EMA10 平仓 | 价 {current_price:.2f} 涨破 EMA10 {ema10:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_low_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
if atr14 is not None and self._candle_low_seen and (current_price - self._candle_low_seen) >= self.atr_multiplier * atr14:
|
||||
logger.info(LOG_POSITION + f"空单 ATR 追踪止盈 | 最低 {self._candle_low_seen:.2f} 当前 {current_price:.2f} 反弹≥{self.atr_multiplier}×ATR={atr14:.2f}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_low_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
pnl_usd = self.get_unrealized_pnl_usd()
|
||||
if pnl_usd is not None:
|
||||
# 固定止损:亏损达到 3 美元平仓
|
||||
if pnl_usd <= self.stop_loss_usd:
|
||||
logger.info(LOG_POSITION + f"固定止损平仓 | 亏损 {pnl_usd:.2f} 美元")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
# 更新持仓期间最大盈利(用于移动止损)
|
||||
if self.max_unrealized_pnl_seen is None:
|
||||
self.max_unrealized_pnl_seen = pnl_usd
|
||||
else:
|
||||
self.max_unrealized_pnl_seen = max(self.max_unrealized_pnl_seen, pnl_usd)
|
||||
# 移动止损:盈利曾达到 activation 后,从最高盈利回撤 trailing_distance 则平仓
|
||||
if self.max_unrealized_pnl_seen >= self.trailing_activation_usd:
|
||||
if pnl_usd < self.max_unrealized_pnl_seen - self.trailing_distance_usd:
|
||||
logger.info(LOG_POSITION + f"移动止损平仓 | 盈利 {pnl_usd:.2f} 从最高 {self.max_unrealized_pnl_seen:.2f} 回撤≥{self.trailing_distance_usd}$")
|
||||
use_fixed = self.drop_from_high_mode == 'fixed' and self.drop_from_high_to_close and self.drop_from_high_to_close > 0
|
||||
use_pct = self.drop_from_high_mode == 'pct_retrace'
|
||||
if use_fixed or use_pct:
|
||||
if self.start == 1: # 多头:最高价已在上面更新,这里只做回落判断
|
||||
do_close = False
|
||||
if use_fixed and self._candle_high_seen and current_price <= self._candle_high_seen - self.drop_from_high_to_close:
|
||||
do_close = True
|
||||
reason = f"固定回落 {self.drop_from_high_to_close}"
|
||||
elif use_pct and self._candle_high_seen and current_kline.get('open'):
|
||||
candle_open = float(current_kline['open'])
|
||||
rise_pct = (self._candle_high_seen - candle_open) / candle_open * 100 if candle_open > 0 else 0
|
||||
if rise_pct >= self.min_rise_pct_to_activate:
|
||||
drop_trigger_pct = max(self.min_drop_pct_from_high, rise_pct * self.retrace_ratio)
|
||||
drop_pct = (self._candle_high_seen - current_price) / self._candle_high_seen * 100 if self._candle_high_seen else 0
|
||||
if drop_pct >= drop_trigger_pct:
|
||||
do_close = True
|
||||
reason = f"涨幅 {rise_pct:.3f}% → 允许回撤 {drop_trigger_pct:.3f}%,实际回撤 {drop_pct:.3f}%"
|
||||
else:
|
||||
pass # 涨幅不足,不启用动态回撤
|
||||
if do_close:
|
||||
logger.info(LOG_POSITION + f"多单K线回落平仓 | 最高 {self._candle_high_seen:.2f} 当前 {current_price:.2f} | {reason}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_high_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
elif self.start == -1: # 空头:跟踪当前K线最低价,从最低点反弹超过阈值则平仓
|
||||
self._candle_low_seen = min(self._candle_low_seen or float('inf'), current_price)
|
||||
do_close = False
|
||||
if use_fixed and self._candle_low_seen and current_price >= self._candle_low_seen + self.drop_from_high_to_close:
|
||||
do_close = True
|
||||
reason = f"固定反弹 {self.drop_from_high_to_close}"
|
||||
elif use_pct and self._candle_low_seen and current_kline.get('open'):
|
||||
candle_open = float(current_kline['open'])
|
||||
rise_pct = (candle_open - self._candle_low_seen) / candle_open * 100 if candle_open > 0 else 0 # 对空头是“跌幅”
|
||||
if rise_pct >= self.min_rise_pct_to_activate:
|
||||
drop_trigger_pct = max(self.min_drop_pct_from_high, rise_pct * self.retrace_ratio)
|
||||
bounce_pct = (current_price - self._candle_low_seen) / self._candle_low_seen * 100 if self._candle_low_seen else 0
|
||||
if bounce_pct >= drop_trigger_pct:
|
||||
do_close = True
|
||||
reason = f"跌幅 {rise_pct:.3f}% → 允许反弹 {drop_trigger_pct:.3f}%,实际反弹 {bounce_pct:.3f}%"
|
||||
if do_close:
|
||||
logger.info(LOG_POSITION + f"空单K线反弹平仓 | 最低 {self._candle_low_seen:.2f} 当前 {current_price:.2f} | {reason}")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
self._candle_low_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
pnl_usd = self.get_unrealized_pnl_usd()
|
||||
if pnl_usd is not None:
|
||||
# 固定止损:亏损达到 3 美元平仓
|
||||
if pnl_usd <= self.stop_loss_usd:
|
||||
logger.info(LOG_POSITION + f"固定止损平仓 | 亏损 {pnl_usd:.2f} 美元")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
# 4. 检查信号
|
||||
signal = self.check_signal(current_price, prev_kline, current_kline)
|
||||
# 更新持仓期间最大盈利(用于移动止损)
|
||||
if self.max_unrealized_pnl_seen is None:
|
||||
self.max_unrealized_pnl_seen = pnl_usd
|
||||
else:
|
||||
self.max_unrealized_pnl_seen = max(self.max_unrealized_pnl_seen, pnl_usd)
|
||||
# 移动止损:盈利曾达到 activation 后,从最高盈利回撤 trailing_distance 则平仓
|
||||
if self.max_unrealized_pnl_seen >= self.trailing_activation_usd:
|
||||
if pnl_usd < self.max_unrealized_pnl_seen - self.trailing_distance_usd:
|
||||
logger.info(LOG_POSITION + f"移动止损平仓 | 盈利 {pnl_usd:.2f} 从最高 {self.max_unrealized_pnl_seen:.2f} 回撤≥{self.trailing_distance_usd}$")
|
||||
self.平仓()
|
||||
self.max_unrealized_pnl_seen = None
|
||||
time.sleep(3)
|
||||
continue
|
||||
# 4. 检查信号
|
||||
signal = self.check_signal(current_price, prev_kline, current_kline)
|
||||
|
||||
# 5. 反手过滤:冷却时间 + 最小价差
|
||||
if signal and signal[0].startswith('reverse_'):
|
||||
if not self.can_reverse(current_price, signal[1]):
|
||||
signal = None
|
||||
# 5. 反手过滤:冷却时间 + 最小价差
|
||||
if signal and signal[0].startswith('reverse_'):
|
||||
if not self.can_reverse(current_price, signal[1]):
|
||||
signal = None
|
||||
|
||||
# 5.5 开仓频率过滤:仅冷却时间,单根 K 线符合规则可多次开仓
|
||||
if signal and signal[0] in ('long', 'short'):
|
||||
if not self.can_open(current_kline_time):
|
||||
signal = None
|
||||
else:
|
||||
self._current_kline_id_for_open = current_kline_time # 供 execute_trade 成功后记录
|
||||
# 5.5 开仓频率过滤:仅冷却时间,单根 K 线符合规则可多次开仓
|
||||
if signal and signal[0] in ('long', 'short'):
|
||||
if not self.can_open(current_kline_time):
|
||||
signal = None
|
||||
else:
|
||||
self._current_kline_id_for_open = current_kline_time # 供 execute_trade 成功后记录
|
||||
|
||||
# 6. 有信号则执行交易
|
||||
if signal:
|
||||
trade_success = self.execute_trade(signal)
|
||||
if trade_success:
|
||||
logger.success(LOG_POSITION + f"交易执行完成: {signal[0]} | 当前持仓: {self.start}")
|
||||
page_start = True
|
||||
else:
|
||||
logger.warning(f"交易执行失败或被阻止: {signal[0]}")
|
||||
# 6. 有信号则执行交易
|
||||
if signal:
|
||||
trade_success = self.execute_trade(signal)
|
||||
if trade_success:
|
||||
logger.success(LOG_POSITION + f"交易执行完成: {signal[0]} | 当前持仓: {self.start}")
|
||||
page_start = True
|
||||
else:
|
||||
logger.warning(f"交易执行失败或被阻止: {signal[0]}")
|
||||
|
||||
# 短暂等待后继续循环(同一根K线遇到信号就操作)
|
||||
time.sleep(0.1)
|
||||
# 短暂等待后继续循环(同一根K线遇到信号就操作)
|
||||
time.sleep(0.1)
|
||||
|
||||
if page_start:
|
||||
self.page.close()
|
||||
if page_start:
|
||||
self.page.close()
|
||||
time.sleep(5)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info(LOG_SYSTEM + "用户中断,程序退出")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"主循环异常: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info(LOG_SYSTEM + "用户中断,程序退出")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"主循环异常: {e}")
|
||||
time.sleep(5)
|
||||
finally:
|
||||
if live is not None:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user