datacom-device-api 0.1.8__tar.gz → 0.1.10__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.8 → datacom_device_api-0.1.10}/PKG-INFO +1 -1
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/pyproject.toml +1 -1
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/process/terminal_process.py +62 -11
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/PKG-INFO +1 -1
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/README.md +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/setup.cfg +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/__init__.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/data/__init__.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/data/table.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/event/event.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/ext/ext_meta.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/ext/ext_meta_display.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/__init__.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_operation.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_read_from_xlsx.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/operation/table_save_to_db.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/process/__init__.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/__init__.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/directory_util.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/logger.py +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/SOURCES.txt +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/dependency_links.txt +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/requires.txt +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/top_level.txt +0 -0
- {datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/test/test_table_matching.py +0 -0
|
@@ -15,6 +15,7 @@ from typing import Any, Callable, Optional, ParamSpec, Protocol, TypeVar, runtim
|
|
|
15
15
|
from uuid import UUID
|
|
16
16
|
import uuid
|
|
17
17
|
|
|
18
|
+
from rich.console import Console
|
|
18
19
|
from rich.progress import Progress, TaskID
|
|
19
20
|
|
|
20
21
|
|
|
@@ -60,15 +61,17 @@ class TerminalProcess:
|
|
|
60
61
|
process.submit(task2)
|
|
61
62
|
"""
|
|
62
63
|
|
|
63
|
-
def __init__(self, max_workers: Optional[int] = None):
|
|
64
|
+
def __init__(self, max_workers: Optional[int] = None, console: Optional[Console] = None):
|
|
64
65
|
"""初始化终端进程执行器。
|
|
65
66
|
|
|
66
67
|
Args:
|
|
67
68
|
max_workers: 进程池最大并发数,默认为 CPU 核心数
|
|
69
|
+
console: 共享的 Rich Console 实例,用于日志输出与进度条保持同一终端
|
|
68
70
|
"""
|
|
69
71
|
self.__pool = ProcessPoolExecutor(max_workers=max_workers or os.cpu_count())
|
|
70
72
|
self.__manager = Manager()
|
|
71
73
|
self.__progress_queue: queue.Queue[ProgressMessage] = self.__manager.Queue()
|
|
74
|
+
self.__log_queue: queue.Queue[str] = self.__manager.Queue()
|
|
72
75
|
|
|
73
76
|
self.__task_future_count = 0
|
|
74
77
|
self.__tasks: dict[UUID, Future[Any]] = {}
|
|
@@ -76,7 +79,10 @@ class TerminalProcess:
|
|
|
76
79
|
|
|
77
80
|
self.__progress_thread_stop_event = threading.Event()
|
|
78
81
|
self.__progress_tasks: dict[UUID, TaskID] = {}
|
|
79
|
-
self.
|
|
82
|
+
self.__console = console if console is not None else Console()
|
|
83
|
+
# 让 Progress 固定在终端底部,使用同一个 Console 输出日志时,
|
|
84
|
+
# 日志会显示在进度条之上,进度条始终保持在终端底部
|
|
85
|
+
self.__progress = Progress(console=self.__console)
|
|
80
86
|
self.__progress_thread: Optional[threading.Thread] = None
|
|
81
87
|
self.__progress_main_task: TaskID = self.__progress.add_task(
|
|
82
88
|
'main', total=self.__task_future_count
|
|
@@ -113,10 +119,24 @@ class TerminalProcess:
|
|
|
113
119
|
if message.type == 'done':
|
|
114
120
|
self.__progress.update(self.__progress_main_task, advance=1)
|
|
115
121
|
|
|
122
|
+
def print(self, *args, **kwargs) -> None:
|
|
123
|
+
"""在进度条之上输出日志信息。
|
|
124
|
+
|
|
125
|
+
使用与 Progress 共享的 Console 输出,日志会显示在终端上方,
|
|
126
|
+
进度条始终保持在终端底部。
|
|
127
|
+
"""
|
|
128
|
+
self.__console.print(*args, **kwargs)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def console(self) -> Console:
|
|
132
|
+
"""返回与 Progress 共享的 Console 实例。"""
|
|
133
|
+
return self.__console
|
|
134
|
+
|
|
116
135
|
@staticmethod
|
|
117
136
|
def _warrper_fn(
|
|
118
137
|
fn: EXECUTE_FUNC_TYPE,
|
|
119
138
|
progress_queue: queue.Queue[ProgressMessage],
|
|
139
|
+
log_queue: queue.Queue[str],
|
|
120
140
|
task_id: UUID,
|
|
121
141
|
*args,
|
|
122
142
|
**kwargs,
|
|
@@ -125,7 +145,19 @@ class TerminalProcess:
|
|
|
125
145
|
|
|
126
146
|
封装进度上报、完成标记和异常处理,通过队列将进度消息
|
|
127
147
|
发送回主进程。任务正常结束或异常均会发送对应类型的消息。
|
|
148
|
+
同时配置根 logger 使用 QueueHandler 将子进程日志转发到主进程。
|
|
128
149
|
"""
|
|
150
|
+
import logging
|
|
151
|
+
import logging.handlers
|
|
152
|
+
|
|
153
|
+
root_logger = logging.getLogger()
|
|
154
|
+
queue_handler = logging.handlers.QueueHandler(log_queue)
|
|
155
|
+
queue_handler.setLevel(logging.INFO)
|
|
156
|
+
formatter = logging.Formatter('[%(asctime)s-%(levelname)s](%(name)s): %(message)s')
|
|
157
|
+
queue_handler.setFormatter(formatter)
|
|
158
|
+
root_logger.addHandler(queue_handler)
|
|
159
|
+
root_logger.setLevel(logging.INFO)
|
|
160
|
+
|
|
129
161
|
done_send = False
|
|
130
162
|
|
|
131
163
|
def report(progress: float, total: float, message: str, msg_type: str = 'progress'):
|
|
@@ -165,21 +197,33 @@ class TerminalProcess:
|
|
|
165
197
|
def run_display_progress(self) -> None:
|
|
166
198
|
"""进度消费线程主循环。
|
|
167
199
|
|
|
168
|
-
|
|
200
|
+
持续从队列中取出进度消息和日志消息,进度消息依次更新内置进度条并触发监听器,
|
|
201
|
+
日志消息通过共享 Console 输出到终端(显示在进度条上方)。
|
|
169
202
|
使用带超时的轮询避免阻塞,确保停止事件触发后能及时退出。
|
|
170
203
|
"""
|
|
171
|
-
while not self.__progress_thread_stop_event.is_set() or not self.__progress_queue.empty():
|
|
204
|
+
while not self.__progress_thread_stop_event.is_set() or not self.__progress_queue.empty() or not self.__log_queue.empty():
|
|
172
205
|
try:
|
|
173
206
|
message = self.__progress_queue.get(timeout=0.1)
|
|
174
207
|
self.update_progress(message)
|
|
175
208
|
self.trigger_progress(message.task_id, message)
|
|
176
209
|
except queue.Empty:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
while not self.__log_queue.empty():
|
|
213
|
+
try:
|
|
214
|
+
log_msg = self.__log_queue.get_nowait()
|
|
215
|
+
self.__console.print(log_msg)
|
|
216
|
+
except queue.Empty:
|
|
181
217
|
break
|
|
182
218
|
|
|
219
|
+
if (
|
|
220
|
+
self.__progress_thread_stop_event.is_set()
|
|
221
|
+
and all(futrue.done() for futrue in self.__tasks.values())
|
|
222
|
+
and self.__progress_queue.empty()
|
|
223
|
+
and self.__log_queue.empty()
|
|
224
|
+
):
|
|
225
|
+
break
|
|
226
|
+
|
|
183
227
|
def submit(
|
|
184
228
|
self,
|
|
185
229
|
fn: EXECUTE_FUNC_TYPE,
|
|
@@ -199,7 +243,7 @@ class TerminalProcess:
|
|
|
199
243
|
任务的 Future 对象,可用于获取结果或异常
|
|
200
244
|
"""
|
|
201
245
|
task_id = uuid.uuid4()
|
|
202
|
-
task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, task_id)
|
|
246
|
+
task_fn = partial(TerminalProcess._warrper_fn, fn, self.__progress_queue, self.__log_queue, task_id)
|
|
203
247
|
future = self.__pool.submit(task_fn, *args, **kwargs)
|
|
204
248
|
self.__tasks[task_id] = future
|
|
205
249
|
self.__task_update_lisening_fn_dict[task_id] = []
|
|
@@ -222,8 +266,8 @@ class TerminalProcess:
|
|
|
222
266
|
def shutdown(self) -> None:
|
|
223
267
|
"""停止任务执行并释放资源。
|
|
224
268
|
|
|
225
|
-
按顺序执行:等待所有任务完成 →
|
|
226
|
-
关闭进程池 →
|
|
269
|
+
按顺序执行:等待所有任务完成 → 设置停止事件 → 消费线程退出并消费剩余消息 →
|
|
270
|
+
关闭进程池 → 停止进度条。确保不会因消息未消费完而丢失进度或日志。
|
|
227
271
|
"""
|
|
228
272
|
for future in self.__tasks.values():
|
|
229
273
|
try:
|
|
@@ -236,6 +280,13 @@ class TerminalProcess:
|
|
|
236
280
|
self.__progress_thread.join()
|
|
237
281
|
self.__progress_thread = None
|
|
238
282
|
|
|
283
|
+
while not self.__log_queue.empty():
|
|
284
|
+
try:
|
|
285
|
+
log_msg = self.__log_queue.get_nowait()
|
|
286
|
+
self.__console.print(log_msg)
|
|
287
|
+
except queue.Empty:
|
|
288
|
+
break
|
|
289
|
+
|
|
239
290
|
self.__pool.shutdown(wait=True)
|
|
240
291
|
self.__progress.stop()
|
|
241
292
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/data/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/event/event.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/ext/ext_meta.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/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.8 → datacom_device_api-0.1.10}/src/datacom_device_api/process/__init__.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api/utils/logger.py
RENAMED
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/requires.txt
RENAMED
|
File without changes
|
{datacom_device_api-0.1.8 → datacom_device_api-0.1.10}/src/datacom_device_api.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|