ygo 1.1.6__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ygo might be problematic. Click here for more details.
- ygo/__init__.py +1 -1
- ygo/pool.py +6 -6
- {ygo-1.1.6.dist-info → ygo-1.2.0.dist-info}/METADATA +2 -2
- ygo-1.2.0.dist-info/RECORD +11 -0
- ygo-1.2.0.dist-info/top_level.txt +1 -0
- ygo-1.1.6.dist-info/RECORD +0 -13
- ygo-1.1.6.dist-info/top_level.txt +0 -2
- ylog/__init__.py +0 -23
- ylog/core.py +0 -259
- {ygo-1.1.6.dist-info → ygo-1.2.0.dist-info}/WHEEL +0 -0
- {ygo-1.1.6.dist-info → ygo-1.2.0.dist-info}/licenses/LICENSE +0 -0
ygo/__init__.py
CHANGED
ygo/pool.py
CHANGED
|
@@ -12,8 +12,7 @@ import threading
|
|
|
12
12
|
import warnings
|
|
13
13
|
|
|
14
14
|
from joblib import Parallel, delayed
|
|
15
|
-
|
|
16
|
-
import ylog
|
|
15
|
+
import tolog
|
|
17
16
|
from .exceptions import WarnException, FailTaskError
|
|
18
17
|
from .delay import delay
|
|
19
18
|
|
|
@@ -21,16 +20,17 @@ with warnings.catch_warnings():
|
|
|
21
20
|
warnings.simplefilter("ignore")
|
|
22
21
|
from tqdm.auto import tqdm
|
|
23
22
|
|
|
23
|
+
logger = tolog.get_logger("ygo")
|
|
24
24
|
|
|
25
25
|
def run_job(job, task_id, queue):
|
|
26
26
|
"""执行任务并更新队列"""
|
|
27
27
|
try:
|
|
28
28
|
result = job()
|
|
29
29
|
except WarnException as e:
|
|
30
|
-
|
|
30
|
+
logger.warning(FailTaskError(task_name=job.task_name, error=e))
|
|
31
31
|
result = None
|
|
32
32
|
except Exception as e:
|
|
33
|
-
|
|
33
|
+
logger.error(FailTaskError(task_name=job.task_name, error=e), exc_info=e)
|
|
34
34
|
result = None
|
|
35
35
|
queue.put((task_id, 1))
|
|
36
36
|
return result
|
|
@@ -170,13 +170,13 @@ class pool:
|
|
|
170
170
|
try:
|
|
171
171
|
self._parallel.__exit__(None, None, None)
|
|
172
172
|
except Exception as e:
|
|
173
|
-
|
|
173
|
+
logger.warning(f"Failed to close Parallel: {e}")
|
|
174
174
|
|
|
175
175
|
if hasattr(self, '_manager') and self._manager is not None:
|
|
176
176
|
try:
|
|
177
177
|
self._manager.shutdown()
|
|
178
178
|
except Exception as e:
|
|
179
|
-
|
|
179
|
+
logger.warning(f"Failed to shutdown Manager: {e}")
|
|
180
180
|
|
|
181
181
|
def __enter__(self):
|
|
182
182
|
return self
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ygo
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: 一个轻量级 Python 工具包,支持 并发执行(带进度条)、延迟调用、链式绑定参数、函数信息获取、模块/函数动态加载。并结合 ylog 提供日志记录能力
|
|
5
5
|
Project-URL: homepage, https://github.com/link-yundi/ygo
|
|
6
6
|
Project-URL: repository, https://github.com/link-yundi/ygo
|
|
@@ -9,7 +9,7 @@ Description-Content-Type: text/markdown
|
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: hydra-core>=1.3.2
|
|
11
11
|
Requires-Dist: joblib>=1.5.0
|
|
12
|
-
Requires-Dist:
|
|
12
|
+
Requires-Dist: tolog>=1.0.0
|
|
13
13
|
Requires-Dist: tqdm>=4.67.1
|
|
14
14
|
Dynamic: license-file
|
|
15
15
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ygo/__init__.py,sha256=faltam5_OXcMUKrJFjTaX5T0EAQjClT2S973MWkZrog,727
|
|
2
|
+
ygo/delay.py,sha256=66xtPXqyD630FL7LWL5qJKAIZvyGDwZyM4qPfk8Czlg,2206
|
|
3
|
+
ygo/exceptions.py,sha256=0OYDYt_9KKo8mF2XBG5QkCMr3-ASp69VDSPOEwlIsrI,660
|
|
4
|
+
ygo/lazy.py,sha256=IwWOv3zYWGGuFefvZwZyP-zokyB4EnQWmySstSk3dJg,1320
|
|
5
|
+
ygo/pool.py,sha256=mnao2KtJUKgjSfqdCSZVVGXPrrz_0W-0OzBUjFKsVjk,7093
|
|
6
|
+
ygo/utils.py,sha256=paeYb8TwonIaDwusE6YV9v_-Y-WzVjGgSa_c1mblw3Y,4040
|
|
7
|
+
ygo-1.2.0.dist-info/licenses/LICENSE,sha256=6AKUWQ1xe-jwPSFv_H6FMQLNNWb7AYqzuEUTwlP2S8M,1067
|
|
8
|
+
ygo-1.2.0.dist-info/METADATA,sha256=LnVYXgn_QFcqhWMZY9NDLvUKwXYiZ89AwB-v4eNMFZE,4876
|
|
9
|
+
ygo-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
ygo-1.2.0.dist-info/top_level.txt,sha256=4E07GOD3KS5--r4rP13upXfTEgk3JGJpQmMkdkJ4t74,4
|
|
11
|
+
ygo-1.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ygo
|
ygo-1.1.6.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
ygo/__init__.py,sha256=FLytzQXxm255WUZE_NgdMrKORq3UPE_YDjqRe9xAXDg,728
|
|
2
|
-
ygo/delay.py,sha256=66xtPXqyD630FL7LWL5qJKAIZvyGDwZyM4qPfk8Czlg,2206
|
|
3
|
-
ygo/exceptions.py,sha256=0OYDYt_9KKo8mF2XBG5QkCMr3-ASp69VDSPOEwlIsrI,660
|
|
4
|
-
ygo/lazy.py,sha256=IwWOv3zYWGGuFefvZwZyP-zokyB4EnQWmySstSk3dJg,1320
|
|
5
|
-
ygo/pool.py,sha256=bnHm4TtnRoFBv5UvV7WpuObJoK4FdoRf65mvf82yEyI,7052
|
|
6
|
-
ygo/utils.py,sha256=paeYb8TwonIaDwusE6YV9v_-Y-WzVjGgSa_c1mblw3Y,4040
|
|
7
|
-
ygo-1.1.6.dist-info/licenses/LICENSE,sha256=6AKUWQ1xe-jwPSFv_H6FMQLNNWb7AYqzuEUTwlP2S8M,1067
|
|
8
|
-
ylog/__init__.py,sha256=S_M_Hv_gKI_U9XUNn3rCu5h9NHZndVMRfRjMs2sjHyw,452
|
|
9
|
-
ylog/core.py,sha256=l8vrSgCLQGIeQN_mqw8rMNp3W7m41nqJIH48DHtW16c,9105
|
|
10
|
-
ygo-1.1.6.dist-info/METADATA,sha256=Iy7McK7cGWUbx7KMQv9lDfkcGqVhy4cv7qQnQeeaUxg,4877
|
|
11
|
-
ygo-1.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
-
ygo-1.1.6.dist-info/top_level.txt,sha256=sY7lJBJ2ncfEMAxoNBVay0RVUixpVt9Osuwwy0_uWqU,9
|
|
13
|
-
ygo-1.1.6.dist-info/RECORD,,
|
ylog/__init__.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
---------------------------------------------
|
|
4
|
-
Created on 2025/5/14 15:37
|
|
5
|
-
@author: ZhangYundi
|
|
6
|
-
@email: yundi.xxii@outlook.com
|
|
7
|
-
---------------------------------------------
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from .core import trace, debug, info, warning, error, critical, update_config, get_logger
|
|
11
|
-
|
|
12
|
-
__version__ = "v1.1.4"
|
|
13
|
-
|
|
14
|
-
__all__ = [
|
|
15
|
-
"trace",
|
|
16
|
-
"debug",
|
|
17
|
-
"info",
|
|
18
|
-
"warning",
|
|
19
|
-
"error",
|
|
20
|
-
"critical",
|
|
21
|
-
"update_config",
|
|
22
|
-
"get_logger",
|
|
23
|
-
]
|
ylog/core.py
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
---------------------------------------------
|
|
4
|
-
Created on 2025/5/14 16:04
|
|
5
|
-
@author: ZhangYundi
|
|
6
|
-
@email: yundi.xxii@outlook.com
|
|
7
|
-
---------------------------------------------
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import sys
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from typing import Optional
|
|
13
|
-
|
|
14
|
-
from loguru import logger
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class _Logger:
|
|
18
|
-
"""
|
|
19
|
-
企业级日志类,基于Loguru封装
|
|
20
|
-
|
|
21
|
-
特性:
|
|
22
|
-
1. 高性能:异步写入日志,避免阻塞主线程
|
|
23
|
-
2. 易于管理:多级别日志分离存储,按日期和大小轮转
|
|
24
|
-
3. 分级明确:支持 TRACE/DEBUG/INFO/WARNING/ERROR/CRITICAL 级别
|
|
25
|
-
4. 全局异常捕获:自动记录未处理异常
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def __new__(cls, *args, **kwargs):
|
|
29
|
-
"""移除单例限制,允许自由创建多个实例"""
|
|
30
|
-
return super().__new__(cls)
|
|
31
|
-
|
|
32
|
-
def __init__(
|
|
33
|
-
self,
|
|
34
|
-
log_dir: str = "logs",
|
|
35
|
-
app_name: str | None = None,
|
|
36
|
-
retention_days: int = 7,
|
|
37
|
-
error_retention_days: int = 30,
|
|
38
|
-
enable_console: bool = True,
|
|
39
|
-
enable_file: bool = True,
|
|
40
|
-
debug_mode: bool = False
|
|
41
|
-
):
|
|
42
|
-
"""初始化日志系统"""
|
|
43
|
-
# 避免重复初始化
|
|
44
|
-
if hasattr(self, "_initialized"):
|
|
45
|
-
return
|
|
46
|
-
self._initialized = True
|
|
47
|
-
|
|
48
|
-
# 初始化参数
|
|
49
|
-
self.log_dir = Path(log_dir)
|
|
50
|
-
self.app_name = app_name
|
|
51
|
-
self.debug_mode = debug_mode
|
|
52
|
-
self._error_retention_days = error_retention_days
|
|
53
|
-
self._retention_days = retention_days
|
|
54
|
-
|
|
55
|
-
# 创建日志目录
|
|
56
|
-
self.log_dir.mkdir(parents=True, exist_ok=True)
|
|
57
|
-
|
|
58
|
-
# 移除默认sink
|
|
59
|
-
logger.remove()
|
|
60
|
-
|
|
61
|
-
# 配置控制台日志
|
|
62
|
-
if enable_console:
|
|
63
|
-
self._setup_console_logging()
|
|
64
|
-
|
|
65
|
-
# 配置文件日志
|
|
66
|
-
if enable_file:
|
|
67
|
-
self._setup_file_logging(retention_days, error_retention_days)
|
|
68
|
-
|
|
69
|
-
# 全局异常捕获
|
|
70
|
-
self._setup_global_exception_handling()
|
|
71
|
-
|
|
72
|
-
def _setup_console_logging(self):
|
|
73
|
-
"""配置控制台日志"""
|
|
74
|
-
console_format = (
|
|
75
|
-
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
|
|
76
|
-
"<level>{level: <8}</level> | "
|
|
77
|
-
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
|
|
78
|
-
"<level>{message}</level>"
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
logger.add(
|
|
82
|
-
sys.stderr,
|
|
83
|
-
level="TRACE",
|
|
84
|
-
format=console_format,
|
|
85
|
-
colorize=True,
|
|
86
|
-
backtrace=self.debug_mode,
|
|
87
|
-
diagnose=self.debug_mode,
|
|
88
|
-
# enqueue=True # 异步写入
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
def _setup_file_logging(self, retention_days: int, error_retention_days: int):
|
|
92
|
-
"""配置文件日志"""
|
|
93
|
-
# 通用日志格式
|
|
94
|
-
common_format = (
|
|
95
|
-
"{time:YYYY-MM-DD HH:mm:ss.SSS} | "
|
|
96
|
-
"{level: <8} | "
|
|
97
|
-
"{name}:{function}:{line} - {message}"
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
# 日志级别配置
|
|
101
|
-
levels = {
|
|
102
|
-
"TRACE": {"level": "TRACE", "retention": f"{retention_days} days", "rotation": "daily"},
|
|
103
|
-
"DEBUG": {"level": "DEBUG", "retention": f"{retention_days} days", "rotation": "daily"},
|
|
104
|
-
"INFO": {"level": "INFO", "retention": f"{retention_days} days", "rotation": "daily"},
|
|
105
|
-
"WARNING": {"level": "WARNING", "retention": f"{error_retention_days} days", "rotation": "daily"},
|
|
106
|
-
"ERROR": {"level": "ERROR", "retention": f"{error_retention_days} days", "rotation": "daily"},
|
|
107
|
-
"CRITICAL": {"level": "CRITICAL", "retention": f"{error_retention_days} days", "rotation": "daily"}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
# 错误级别以上的日志
|
|
111
|
-
error_levels = ("ERROR", "CRITICAL")
|
|
112
|
-
_error_log_file = f"{self.app_name}_{{time:YYYYMMDD}}.err.log" if self.app_name is not None else f"{{time:YYYYMMDD}}.err.log"
|
|
113
|
-
error_log_file = self.log_dir / _error_log_file
|
|
114
|
-
info_levels = ("INFO", "DEBUG", "TRACE", "WARNING")
|
|
115
|
-
_info_log_file = f"{self.app_name}_{{time:YYYYMMDD}}.log" if self.app_name is not None else f"{{time:YYYYMMDD}}.log"
|
|
116
|
-
info_log_file = self.log_dir / _info_log_file
|
|
117
|
-
# 错误级别以上的日志
|
|
118
|
-
logger.add(
|
|
119
|
-
str(error_log_file),
|
|
120
|
-
level="ERROR",
|
|
121
|
-
format=common_format,
|
|
122
|
-
rotation=levels["ERROR"]["rotation"],
|
|
123
|
-
retention=levels["ERROR"]["retention"],
|
|
124
|
-
compression="zip",
|
|
125
|
-
backtrace=True,
|
|
126
|
-
diagnose=self.debug_mode,
|
|
127
|
-
# enqueue=True, # 异步写入
|
|
128
|
-
filter=lambda record: record["level"].name in error_levels,
|
|
129
|
-
catch=True # 捕获格式化异常
|
|
130
|
-
)
|
|
131
|
-
# 错误级别以下的日志
|
|
132
|
-
logger.add(
|
|
133
|
-
str(info_log_file),
|
|
134
|
-
level="TRACE",
|
|
135
|
-
format=common_format,
|
|
136
|
-
rotation=levels["INFO"]["rotation"],
|
|
137
|
-
retention=levels["INFO"]["retention"],
|
|
138
|
-
compression="zip",
|
|
139
|
-
backtrace=True,
|
|
140
|
-
diagnose=self.debug_mode,
|
|
141
|
-
# enqueue=True, # 异步写入
|
|
142
|
-
filter=lambda record: record["level"].name in info_levels,
|
|
143
|
-
catch=True # 捕获格式化异常
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
def _setup_global_exception_handling(self):
|
|
147
|
-
"""配置全局异常捕获"""
|
|
148
|
-
|
|
149
|
-
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
150
|
-
"""全局异常处理函数"""
|
|
151
|
-
logger.opt(exception=(exc_type, exc_value, exc_traceback)).critical(
|
|
152
|
-
"Unhandled exception occurred"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
sys.excepthook = handle_exception
|
|
156
|
-
|
|
157
|
-
def _msgs_to_str(self, *msg: str) -> str:
|
|
158
|
-
return " ".join([str(m) for m in msg])
|
|
159
|
-
|
|
160
|
-
def trace(self, *msg: str, **kwargs) -> None:
|
|
161
|
-
"""TRACE级别日志"""
|
|
162
|
-
logger.opt(depth=1).trace(self._msgs_to_str(*msg), **kwargs)
|
|
163
|
-
|
|
164
|
-
def debug(self, *msg: str, **kwargs) -> None:
|
|
165
|
-
"""DEBUG级别日志"""
|
|
166
|
-
logger.opt(depth=1).debug(self._msgs_to_str(*msg), **kwargs)
|
|
167
|
-
|
|
168
|
-
def info(self, *msg: str, **kwargs) -> None:
|
|
169
|
-
"""INFO级别日志"""
|
|
170
|
-
logger.opt(depth=1).info(self._msgs_to_str(*msg), **kwargs)
|
|
171
|
-
|
|
172
|
-
def warning(self, *msg: str, **kwargs) -> None:
|
|
173
|
-
"""WARNING级别日志"""
|
|
174
|
-
logger.opt(depth=1).warning(self._msgs_to_str(*msg), **kwargs)
|
|
175
|
-
|
|
176
|
-
def error(self, *msg: str, exc_info: Optional[BaseException] = None, **kwargs) -> None:
|
|
177
|
-
"""ERROR级别日志"""
|
|
178
|
-
if exc_info:
|
|
179
|
-
logger.opt(depth=1, exception=exc_info).error(self._msgs_to_str(*msg), **kwargs)
|
|
180
|
-
else:
|
|
181
|
-
logger.opt(depth=1).error(self._msgs_to_str(*msg), **kwargs)
|
|
182
|
-
|
|
183
|
-
def critical(self, *msg: str, exc_info: Optional[BaseException] = None, **kwargs) -> None:
|
|
184
|
-
"""CRITICAL级别日志"""
|
|
185
|
-
if exc_info:
|
|
186
|
-
logger.opt(depth=1, exception=exc_info).critical(self._msgs_to_str(*msg), **kwargs)
|
|
187
|
-
else:
|
|
188
|
-
logger.opt(depth=1).critical(self._msgs_to_str(*msg), **kwargs)
|
|
189
|
-
|
|
190
|
-
def update_config(
|
|
191
|
-
self,
|
|
192
|
-
log_dir: str = None,
|
|
193
|
-
app_name: str = None,
|
|
194
|
-
retention_days: int = None,
|
|
195
|
-
error_retention_days: int = None,
|
|
196
|
-
enable_console: bool = None,
|
|
197
|
-
enable_file: bool = None,
|
|
198
|
-
debug_mode: bool = None
|
|
199
|
-
):
|
|
200
|
-
"""
|
|
201
|
-
动态更新日志配置并重新加载日志系统
|
|
202
|
-
注意:这会清除已有的sink并重新创建日志文件
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
# 更新配置
|
|
206
|
-
if log_dir is not None:
|
|
207
|
-
self.log_dir = Path(log_dir)
|
|
208
|
-
if app_name is not None:
|
|
209
|
-
self.app_name = app_name
|
|
210
|
-
if retention_days is not None:
|
|
211
|
-
self._retention_days = retention_days
|
|
212
|
-
if error_retention_days is not None:
|
|
213
|
-
self._error_retention_days = error_retention_days
|
|
214
|
-
if debug_mode is not None:
|
|
215
|
-
self.debug_mode = debug_mode
|
|
216
|
-
|
|
217
|
-
# 重建日志目录
|
|
218
|
-
self.log_dir.mkdir(parents=True, exist_ok=True)
|
|
219
|
-
|
|
220
|
-
# 清除现有sink
|
|
221
|
-
logger.remove()
|
|
222
|
-
|
|
223
|
-
# 重新配置控制台和文件日志
|
|
224
|
-
if enable_console is not False:
|
|
225
|
-
self._setup_console_logging()
|
|
226
|
-
if enable_file is not False:
|
|
227
|
-
self._setup_file_logging(self._retention_days, self._error_retention_days)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
# 初始化默认实例
|
|
231
|
-
_default_logger = _Logger()
|
|
232
|
-
|
|
233
|
-
# 将日志方法绑定到模块级别
|
|
234
|
-
trace = _default_logger.trace
|
|
235
|
-
debug = _default_logger.debug
|
|
236
|
-
info = _default_logger.info
|
|
237
|
-
warning = _default_logger.warning
|
|
238
|
-
error = _default_logger.error
|
|
239
|
-
critical = _default_logger.critical
|
|
240
|
-
update_config = _default_logger.update_config
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
def get_logger(app_name: str,
|
|
244
|
-
log_dir: str = "logs",
|
|
245
|
-
retention_days: int = 7,
|
|
246
|
-
error_retention_days: int = 30,
|
|
247
|
-
enable_console: bool = True,
|
|
248
|
-
enable_file: bool = True,
|
|
249
|
-
debug_mode: bool = False):
|
|
250
|
-
"""获取指定应用的日志实例"""
|
|
251
|
-
return _Logger(
|
|
252
|
-
app_name=app_name,
|
|
253
|
-
log_dir=log_dir,
|
|
254
|
-
retention_days=retention_days,
|
|
255
|
-
error_retention_days=error_retention_days,
|
|
256
|
-
enable_console=enable_console,
|
|
257
|
-
enable_file=enable_file,
|
|
258
|
-
debug_mode=debug_mode
|
|
259
|
-
)
|
|
File without changes
|
|
File without changes
|