datacom-device-api 0.1.9__tar.gz → 0.1.11__tar.gz
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.
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/PKG-INFO +1 -1
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/pyproject.toml +1 -1
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/process/terminal_process.py +44 -8
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/PKG-INFO +1 -1
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/README.md +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/setup.cfg +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/__init__.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/data/__init__.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/data/table.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/event/event.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/ext/ext_meta.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/ext/ext_meta_display.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/operation/__init__.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/operation/table_operation.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/operation/table_read_from_xlsx.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/operation/table_save_to_db.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/process/__init__.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/utils/__init__.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/utils/directory_util.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/utils/logger.py +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/SOURCES.txt +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/dependency_links.txt +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/requires.txt +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/top_level.txt +0 -0
- {datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/test/test_table_matching.py +0 -0
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
from concurrent.futures import Future, ProcessPoolExecutor
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from functools import partial
|
|
10
|
+
import logging
|
|
11
|
+
from logging.handlers import QueueHandler, QueueListener
|
|
10
12
|
from multiprocessing import Manager
|
|
11
13
|
import os
|
|
12
14
|
import queue
|
|
@@ -49,6 +51,22 @@ class ProgressMessage:
|
|
|
49
51
|
__PROGRESS_UPDATE_FN_TYPE = Callable[[ProgressMessage], None]
|
|
50
52
|
|
|
51
53
|
|
|
54
|
+
class _ConsoleLogHandler(logging.Handler):
|
|
55
|
+
"""将日志输出到 Rich Console,确保日志显示在进度条上方。"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, console: Console):
|
|
58
|
+
super().__init__()
|
|
59
|
+
self.__console = console
|
|
60
|
+
self.setFormatter(logging.Formatter('[%(asctime)s-%(levelname)s](%(name)s): %(message)s'))
|
|
61
|
+
|
|
62
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
63
|
+
try:
|
|
64
|
+
msg = self.format(record)
|
|
65
|
+
self.__console.print(msg)
|
|
66
|
+
except Exception:
|
|
67
|
+
self.handleError(record)
|
|
68
|
+
|
|
69
|
+
|
|
52
70
|
class TerminalProcess:
|
|
53
71
|
"""多进程任务执行器,支持进度展示与监听器机制。
|
|
54
72
|
|
|
@@ -71,6 +89,7 @@ class TerminalProcess:
|
|
|
71
89
|
self.__pool = ProcessPoolExecutor(max_workers=max_workers or os.cpu_count())
|
|
72
90
|
self.__manager = Manager()
|
|
73
91
|
self.__progress_queue: queue.Queue[ProgressMessage] = self.__manager.Queue()
|
|
92
|
+
self.__log_queue: queue.Queue[str] = self.__manager.Queue()
|
|
74
93
|
|
|
75
94
|
self.__task_future_count = 0
|
|
76
95
|
self.__tasks: dict[UUID, Future[Any]] = {}
|
|
@@ -87,6 +106,10 @@ class TerminalProcess:
|
|
|
87
106
|
'main', total=self.__task_future_count
|
|
88
107
|
)
|
|
89
108
|
|
|
109
|
+
# 日志队列监听器:从 log_queue 消费 LogRecord 并输出到 Console
|
|
110
|
+
self.__log_handler = _ConsoleLogHandler(self.__console)
|
|
111
|
+
self.__log_listener = QueueListener(self.__log_queue, self.__log_handler)
|
|
112
|
+
|
|
90
113
|
def trigger_progress(self, task_id: UUID, message: ProgressMessage) -> None:
|
|
91
114
|
"""触发指定任务的所有进度监听器。
|
|
92
115
|
|
|
@@ -135,6 +158,7 @@ class TerminalProcess:
|
|
|
135
158
|
def _warrper_fn(
|
|
136
159
|
fn: EXECUTE_FUNC_TYPE,
|
|
137
160
|
progress_queue: queue.Queue[ProgressMessage],
|
|
161
|
+
log_queue: queue.Queue[str],
|
|
138
162
|
task_id: UUID,
|
|
139
163
|
*args,
|
|
140
164
|
**kwargs,
|
|
@@ -143,7 +167,13 @@ class TerminalProcess:
|
|
|
143
167
|
|
|
144
168
|
封装进度上报、完成标记和异常处理,通过队列将进度消息
|
|
145
169
|
发送回主进程。任务正常结束或异常均会发送对应类型的消息。
|
|
170
|
+
同时配置根 logger 使用 QueueHandler 将子进程日志转发到主进程。
|
|
146
171
|
"""
|
|
172
|
+
root_logger = logging.getLogger()
|
|
173
|
+
queue_handler = QueueHandler(log_queue)
|
|
174
|
+
root_logger.addHandler(queue_handler)
|
|
175
|
+
root_logger.setLevel(logging.INFO)
|
|
176
|
+
|
|
147
177
|
done_send = False
|
|
148
178
|
|
|
149
179
|
def report(progress: float, total: float, message: str, msg_type: str = 'progress'):
|
|
@@ -185,6 +215,7 @@ class TerminalProcess:
|
|
|
185
215
|
|
|
186
216
|
持续从队列中取出进度消息,依次更新内置进度条并触发监听器。
|
|
187
217
|
使用带超时的轮询避免阻塞,确保停止事件触发后能及时退出。
|
|
218
|
+
日志消息由 QueueListener 在后台线程中消费并输出到终端。
|
|
188
219
|
"""
|
|
189
220
|
while not self.__progress_thread_stop_event.is_set() or not self.__progress_queue.empty():
|
|
190
221
|
try:
|
|
@@ -192,11 +223,14 @@ class TerminalProcess:
|
|
|
192
223
|
self.update_progress(message)
|
|
193
224
|
self.trigger_progress(message.task_id, message)
|
|
194
225
|
except queue.Empty:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
199
|
-
|
|
226
|
+
pass
|
|
227
|
+
|
|
228
|
+
if (
|
|
229
|
+
self.__progress_thread_stop_event.is_set()
|
|
230
|
+
and all(futrue.done() for futrue in self.__tasks.values())
|
|
231
|
+
and self.__progress_queue.empty()
|
|
232
|
+
):
|
|
233
|
+
break
|
|
200
234
|
|
|
201
235
|
def submit(
|
|
202
236
|
self,
|
|
@@ -217,7 +251,7 @@ class TerminalProcess:
|
|
|
217
251
|
任务的 Future 对象,可用于获取结果或异常
|
|
218
252
|
"""
|
|
219
253
|
task_id = uuid.uuid4()
|
|
220
|
-
task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, task_id)
|
|
254
|
+
task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, self.__log_queue, task_id)
|
|
221
255
|
future = self.__pool.submit(task_fn, *args, **kwargs)
|
|
222
256
|
self.__tasks[task_id] = future
|
|
223
257
|
self.__task_update_lisening_fn_dict[task_id] = []
|
|
@@ -233,6 +267,7 @@ class TerminalProcess:
|
|
|
233
267
|
def start(self) -> None:
|
|
234
268
|
"""启动进度条显示与消息消费线程。"""
|
|
235
269
|
self.__progress.start()
|
|
270
|
+
self.__log_listener.start()
|
|
236
271
|
self.__progress_thread_stop_event.clear()
|
|
237
272
|
self.__progress_thread = threading.Thread(target=self.run_display_progress)
|
|
238
273
|
self.__progress_thread.start()
|
|
@@ -240,8 +275,8 @@ class TerminalProcess:
|
|
|
240
275
|
def shutdown(self) -> None:
|
|
241
276
|
"""停止任务执行并释放资源。
|
|
242
277
|
|
|
243
|
-
按顺序执行:等待所有任务完成 →
|
|
244
|
-
关闭进程池 →
|
|
278
|
+
按顺序执行:等待所有任务完成 → 设置停止事件 → 消费线程退出并消费剩余消息 →
|
|
279
|
+
关闭进程池 → 停止进度条。确保不会因消息未消费完而丢失进度或日志。
|
|
245
280
|
"""
|
|
246
281
|
for future in self.__tasks.values():
|
|
247
282
|
try:
|
|
@@ -254,6 +289,7 @@ class TerminalProcess:
|
|
|
254
289
|
self.__progress_thread.join()
|
|
255
290
|
self.__progress_thread = None
|
|
256
291
|
|
|
292
|
+
self.__log_listener.stop()
|
|
257
293
|
self.__pool.shutdown(wait=True)
|
|
258
294
|
self.__progress.stop()
|
|
259
295
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/data/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/event/event.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/ext/ext_meta.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/operation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/process/__init__.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api/utils/logger.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/requires.txt
RENAMED
|
File without changes
|
{datacom_device_api-0.1.9 → datacom_device_api-0.1.11}/src/datacom_device_api.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|