Skip to content

Commit 950a477

Browse files
committed
feat: 接入 Python logging 并重构规范 jm_log,修复 ExceptionListener 参数规范
1 parent 99f5c6d commit 950a477

7 files changed

Lines changed: 67 additions & 29 deletions

File tree

assets/docs/sources/tutorial/11_log_custom.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88

99
使用代码:
1010

11-
```
11+
```python
1212
from jmcomic import disable_jm_log
1313
disable_jm_log()
14+
15+
# 推荐使用 Python 原生的 logging 控制
16+
import logging
17+
logging.getLogger("jmcomic").setLevel(logging.WARNING) # 只显示警告以上的日志
1418
```
1519

1620
使用配置:

assets/docs/sources/tutorial/4_module_custom.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,32 @@ def custom_album_photo_image_detail_class():
137137
```python
138138
def custom_jm_log():
139139
"""
140-
该函数演示自定义log
140+
该函数演示如何接管和自定义日志输出
141141
"""
142142

143-
# jmcomic模块在运行过程中会使用 jm_log() 这个函数进行打印信息
144-
# jm_log() 这个函数 最后会调用 JmModuleConfig.EXECUTOR_LOG 函数
145-
# 你可以写一个自己的函数,替换 JmModuleConfig.EXECUTOR_LOG,实现自定义log
143+
# jmcomic 项目默认使用内置的 Python logging 模块
144+
# 其日志记录器的名字固定为 "jmcomic"
146145

147-
# 1. 自定义log函数
148-
def my_log(topic: str, msg: str):
146+
# 【推荐方式】直接配置原生的 logging logger
147+
import logging
148+
jm_logger = logging.getLogger("jmcomic")
149+
150+
# 例如,取消默认往下游控制台打印的 Handler,转存到文件中
151+
jm_logger.handlers.clear()
152+
jm_logger.addHandler(logging.FileHandler("jm_download.log", encoding="utf-8"))
153+
154+
# 【向后兼容方式/遗留用法】
155+
# 你依然可以通过替换全局配置类的 EXECUTOR_LOG 函数暴力接管日志
156+
def my_custom_log(topic: str, msg, e: Exception = None):
149157
"""
150-
这个log函数的参数列表必须包含两个参数,topic和msg
151158
@param topic: log主题,例如 'album.before', 'req.error', 'plugin.error'
152-
@param msg: 具体log的信息
159+
@param msg: 具体log的信息,也可以直接传入 Exception 对象(底层会自动适配)
160+
@param e: 可选,异常对象(当 msg 本身就是 Exception 时无需传)
153161
"""
154162
pass
155163

156-
# 2. 让my_log生效
157-
JmModuleConfig.EXECUTOR_LOG = my_log
164+
# 生效自定义的 proxy
165+
JmModuleConfig.EXECUTOR_LOG = my_custom_log
158166
```
159167

160168

src/jmcomic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# 被依赖方 <--- 使用方
33
# config <--- entity <--- toolkit <--- client <--- option <--- downloader
44

5-
__version__ = '2.6.14'
5+
__version__ = '2.6.15'
66

77
from .api import *
88
from .jm_plugin import *

src/jmcomic/jm_config.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import logging
2+
13
from common import time_stamp, field_cache, ProxyBuilder
24

5+
jm_logger = logging.getLogger('jmcomic')
6+
37

48
def shuffled(lines):
59
from random import shuffle
@@ -9,9 +13,27 @@ def shuffled(lines):
913
return ls
1014

1115

12-
def default_jm_logging(topic: str, msg: str):
13-
from common import format_ts, current_thread
14-
print('[{}] [{}]:【{}】{}'.format(format_ts(), current_thread().name, topic, msg))
16+
def setup_default_jm_logger():
17+
# 为了保持原有默认向下兼容,如果没有 handler,我们加一个控制台 handler
18+
if not jm_logger.handlers:
19+
import sys
20+
handler = logging.StreamHandler(sys.stdout)
21+
formatter = logging.Formatter('[%(asctime)s] [%(threadName)s]:【%(topic)s】%(message)s', datefmt='%Y-%m-%d %H:%M:%S')
22+
handler.setFormatter(formatter)
23+
jm_logger.addHandler(handler)
24+
jm_logger.setLevel(logging.INFO)
25+
26+
27+
def default_jm_logging(topic: str, msg, e: Exception = None):
28+
# 支持 jm_log('topic', e) 的简写
29+
if isinstance(msg, BaseException):
30+
e = msg
31+
msg = str(msg)
32+
extra = {'topic': topic}
33+
if e is not None:
34+
jm_logger.error(msg, extra=extra, exc_info=e)
35+
else:
36+
jm_logger.info(msg, extra=extra)
1537

1638

1739
# 禁漫常量
@@ -382,11 +404,10 @@ def get_fix_ts_token_tokenparam(cls):
382404
token, tokenparam = JmCryptoTool.token_and_tokenparam(ts)
383405
return ts, token, tokenparam
384406

385-
# noinspection PyUnusedLocal
386407
@classmethod
387-
def jm_log(cls, topic: str, msg: str):
408+
def jm_log(cls, topic: str, msg: str, e: Exception = None):
388409
if cls.FLAG_ENABLE_JM_LOG is True:
389-
cls.EXECUTOR_LOG(topic, msg)
410+
cls.EXECUTOR_LOG(topic, msg, e)
390411

391412
@classmethod
392413
def disable_jm_log(cls):
@@ -507,5 +528,7 @@ def register_exception_listener(cls, etype, listener):
507528
cls.REGISTRY_EXCEPTION_LISTENER[etype] = listener
508529

509530

531+
setup_default_jm_logger()
532+
510533
jm_log = JmModuleConfig.jm_log
511534
disable_jm_log = JmModuleConfig.disable_jm_log

src/jmcomic/jm_exception.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class JmcomicException(Exception):
66
description = 'jmcomic 模块异常'
77

88
def __init__(self, msg: str, context: dict):
9+
super().__init__(msg)
910
self.msg = msg
1011
self.context = context
1112

src/jmcomic/jm_option.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ def call_all_plugin(self, group: str, safe=True, **extra):
541541
self.invoke_plugin(pclass, kwargs, extra, pinfo)
542542
except BaseException as e:
543543
if safe is True:
544-
traceback_print_exec()
544+
jm_log('plugin.exception', e)
545545
else:
546546
raise e
547547

src/jmcomic/jm_plugin.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -552,15 +552,19 @@ def invoke(self, whitelist) -> None:
552552
if whitelist is not None:
553553
whitelist = set(whitelist)
554554

555-
old_jm_log = JmModuleConfig.EXECUTOR_LOG
555+
import logging
556+
from jmcomic import jm_logger
556557

557-
def new_jm_log(topic, msg):
558-
if whitelist is not None and topic not in whitelist:
559-
return
560-
561-
old_jm_log(topic, msg)
558+
class TopicFilter(logging.Filter):
559+
def filter(self, record):
560+
topic = getattr(record, 'topic', None)
561+
if whitelist is not None and topic is not None and topic not in whitelist:
562+
return False
563+
return True
562564

563-
JmModuleConfig.EXECUTOR_LOG = new_jm_log
565+
# 删除旧的同类 filter 避免重复
566+
jm_logger.filters = [f for f in jm_logger.filters if not isinstance(f, TopicFilter)]
567+
jm_logger.addFilter(TopicFilter())
564568

565569

566570
class AutoSetBrowserCookiesPlugin(JmOptionPlugin):
@@ -1286,9 +1290,7 @@ def do_request(domain):
12861290
try:
12871291
return do_request(domain)
12881292
except Exception as e:
1289-
from common import traceback_print_exec
1290-
traceback_print_exec()
1291-
jm_log('req.error', str(e))
1293+
jm_log('req.error', e)
12921294
self.update_failed_count(client, domain)
12931295

12941296
return client.fallback(request, url, 0, 0, is_image, **kwargs)

0 commit comments

Comments
 (0)