diff --git a/common/log.py b/common/log.py index 83d26d7..b436cc3 100644 --- a/common/log.py +++ b/common/log.py @@ -10,11 +10,18 @@ import logging import colorlog import os +import sys +import re +import traceback from pygments import highlight from pygments.lexers import PythonLexer from pygments.formatters import TerminalFormatter from .utils import filterFileName, addToGlobalNamespace from .variable import debug_mode, log_length_limit, log_file +from colorama import Fore, Back, Style +from colorama import init as clinit + +clinit() # 初始化 colorama if ((not os.path.exists("logs")) and log_file): try: @@ -22,15 +29,113 @@ except: pass +class Color: + """ + 彩色文字处理器 + """ + + def __getattr__(self, k): + return lambda x: f"{getattr(Fore, k.upper())}{x}{Style.RESET_ALL}" + +color = Color() + +def is_rubbish(input_string): + return bool(re.match(r'^\^*$', input_string)) -def highlight_error(error): - # 对堆栈跟踪进行语法高亮 - highlighted_traceback = highlight( - error, PythonLexer(), TerminalFormatter()) +def stack_error(exception): + stack_trace = traceback.format_exception(type(exception), exception, exception.__traceback__) + return ''.join(stack_trace) - # 返回语法高亮后的堆栈跟踪字符串 - return str(highlighted_traceback) +def find_function(file_name, line_number): + with open(file_name, 'r') as file: + lines = file.readlines() + target_line = lines[line_number - 1] # 获取目标行内容 + for name, obj in inspect.getmembers(inspect.currentframe().f_back.f_globals): + if (inspect.isfunction(obj)):# and target_line.lstrip().startswith('def '+obj.__name__)): + return obj.__name__, inspect.getsourcelines(obj)[1] +def python_highlight(code): + return highlight(code, PythonLexer(), TerminalFormatter()) + +def read_code(file_path, target_line_number): + try: + with open(file_path, 'r', encoding='utf-8') as file: + lines = file.readlines() + start = max(0, target_line_number - 4) + end = min(target_line_number + 4, len(lines)) + lineMap = { + 'current': lines[target_line_number - 1], + 'result': lines[start:end] + } + return lineMap + except FileNotFoundError: + sys.stderr.write("日志模块出错,本次日志可能无法记录,请报告给开发者: 处理错误语法高亮时找不到源文件") + except Exception as e: + sys.stderr.write(f"日志模块出错,本次日志可能无法记录,请报告给开发者: \n" + traceback.format_exc()) + +def stack_info(stack_trace_line): + try: + parts = stack_trace_line.split(', ') + file_path = ' '.join(parts[0].split(' ')[1:]) # 提取文件路径 + line_number = int(parts[1].split(' ')[1]) # 提取行号 + function_name = parts[2].split(' ')[1] # 提取函数名 + return file_path, line_number, function_name + except Exception as e: + sys.stderr.write(f"日志模块出错,本次日志可能无法记录,请报告给开发者: \n" + traceback.format_exc()) + +def highlight_error(e): + if (isinstance(e, Exception)): + error = stack_error(e) + else: + error = e + lines = [i.strip() for i in error.split("\n") if i.strip()] + final = [] + ign = False + for i in lines: + if (ign): + ign = False + continue + + if (i.startswith("Traceback (most recent call last):")): + final.append(color.cyan(i)) + elif (i.startswith("During handling of the above exception, another exception occurred:")): + final.append(color.cyan(i)) + elif (i.startswith("The above exception was the direct cause of the following exception:")): + final.append(color.cyan(i)) + elif (i.startswith("File")): + ign = True + p, l, f = stack_info(i) + p = p[1:-1] + + if (p.startswith('<')): + final.append(" " + i + '' if (not (lines[lines.index(i) + 1]).startswith("File")) else f"\n{python_highlight(lines[lines.index(i) + 1])}") + continue + + code = read_code(p, l) + cc = [] + for c in code['result']: + if (c.startswith(code['current'])): + cc.append((' ' * (10 - len(str(l))) + f'{l} >|' + c)) + else: + line_number = l + (code["result"].index(c) - 3) + cc.append((' ' * (10 - len(str(line_number))) + f'{line_number} |' + c)) + code = python_highlight("\n".join(cc)) + p = '"' + p + '"' + final.append(f" File {color.yellow(f'{p}')} in {color.cyan(f)}()\n\n\n{code}\n") + else: + try: + if (is_rubbish(i)): + continue + if (issubclass(require(("builtins." if ("." not in i.split(":")[0]) else "") + i.split(":")[0]), Exception)): + exc = i.split(":")[0] + desc = "" if (len(i.split(":")) == 1) else ':'.join(i.split(":")[1:]).strip() + final.append(color.red(exc) + (": " + color.yellow(desc)) if (desc) else "") + else: + final.append(color.cyan(i)) + except: + # traceback.print_exc() + final.append(i) + return "\n".join(final).replace('\n\n', '\n') class LogHelper(logging.Handler): # 日志转接器 diff --git a/common/variable.py b/common/variable.py index 4772063..ca0cc2e 100644 --- a/common/variable.py +++ b/common/variable.py @@ -52,3 +52,6 @@ def _read_config(key): qdes_lib_loaded = False use_cookie_pool = False running_ports = [] +use_proxy = False +http_proxy = '' +https_proxy = '' diff --git a/main.py b/main.py index ae271a9..0b30634 100644 --- a/main.py +++ b/main.py @@ -264,7 +264,7 @@ async def run_app(): return except OSError as e: - if str(e).startswith("[Errno 98]"): + if (str(e).startswith("[Errno 98]") or str(e).startswith('[Errno 10048]')): logger.error("端口已被占用,请检查\n" + str(e)) logger.info('服务器将在10s后再次尝试启动...') await asyncio.sleep(10)