更新
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""企业微信 RPA 桌面控制台。"""
|
||||
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import queue
|
||||
@@ -210,18 +211,70 @@ PAGES = (
|
||||
|
||||
|
||||
class LogQueue:
|
||||
"""把后台线程的标准输出转发到界面。"""
|
||||
"""把后台线程的标准输出转发到界面,同时留一份带时间戳的磁盘副本。
|
||||
|
||||
界面日志随窗口关闭就没了,出问题时无从回溯——真正卡住发送的那一行往往
|
||||
几分钟前就被刷走了。落盘副本让事后还查得到。
|
||||
"""
|
||||
|
||||
LOG_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logs")
|
||||
KEEP_FILES = 20
|
||||
|
||||
def __init__(self, target_queue):
|
||||
self.target_queue = target_queue
|
||||
self._handle = None
|
||||
self._open_log_file()
|
||||
|
||||
def _open_log_file(self):
|
||||
try:
|
||||
os.makedirs(self.LOG_DIR, exist_ok=True)
|
||||
self._prune_old_logs()
|
||||
stamp = time.strftime("%Y%m%d_%H%M%S")
|
||||
self._handle = open(
|
||||
os.path.join(self.LOG_DIR, f"gui_{stamp}.log"),
|
||||
"a",
|
||||
encoding="utf-8",
|
||||
buffering=1,
|
||||
)
|
||||
except Exception:
|
||||
self._handle = None
|
||||
|
||||
def _prune_old_logs(self):
|
||||
try:
|
||||
files = sorted(
|
||||
glob.glob(os.path.join(self.LOG_DIR, "gui_*.log")),
|
||||
key=os.path.getmtime,
|
||||
)
|
||||
for path in files[: max(0, len(files) - self.KEEP_FILES + 1)]:
|
||||
os.unlink(path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def write(self, message):
|
||||
text = str(message).rstrip()
|
||||
if text:
|
||||
self.target_queue.put(("log", text))
|
||||
if not text:
|
||||
return
|
||||
self.target_queue.put(("log", text))
|
||||
if self._handle is not None:
|
||||
try:
|
||||
self._handle.write(f"{time.strftime('%H:%M:%S')} {text}\n")
|
||||
except Exception:
|
||||
self._handle = None
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
if self._handle is not None:
|
||||
try:
|
||||
self._handle.flush()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
if self._handle is not None:
|
||||
try:
|
||||
self._handle.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._handle = None
|
||||
|
||||
|
||||
class BotThread(threading.Thread):
|
||||
@@ -249,6 +302,14 @@ class BotThread(threading.Thread):
|
||||
if bot is not None:
|
||||
bot.message_batch_window_seconds = seconds
|
||||
|
||||
def _report_progress(self, text):
|
||||
"""把机器人此刻在做什么送到界面上那行进度文字。"""
|
||||
try:
|
||||
self.target_queue.put(("progress", str(text or "")))
|
||||
except Exception:
|
||||
# 进度提示纯属好看,永远不该把轮询带下去
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
bot = None
|
||||
failed = False
|
||||
@@ -264,6 +325,7 @@ class BotThread(threading.Thread):
|
||||
bot._stop_check = self.stop_event
|
||||
bot.safe_window_mode = True
|
||||
bot.auto_activate_window = True
|
||||
bot.progress_cb = self._report_progress
|
||||
|
||||
if not bot.connect(activate=False, wait_if_missing=True):
|
||||
failed = True
|
||||
@@ -3793,6 +3855,8 @@ class App(tk.Tk):
|
||||
self._stop_button.set_enabled(False)
|
||||
if sys.stdout is self._stdout_proxy:
|
||||
sys.stdout = self._original_stdout
|
||||
if self._stdout_proxy is not None:
|
||||
self._stdout_proxy.close()
|
||||
self._stdout_proxy = None
|
||||
if final_state == "error":
|
||||
self._set_status("error", "连接失败")
|
||||
|
||||
Reference in New Issue
Block a user