Skip to content

Commit 95bd7ae

Browse files
committed
6. add queue arg to morebuiltins.logs.LogHelper.bind_handler, to enable async logging with AsyncQueueListener. (like loguru's queue=True)
1 parent 12cb604 commit 95bd7ae

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
4. **Compatibility Warnings**:
1111
1. move `async_logger`, `AsyncQueueListener`, `LogHelper`, `RotatingFileWriter`, and `SizedTimedRotatingFileHandler` from `morebuiltins.funcs` to `morebuiltins.logs`.
1212
5. add `ContextFilter` for logging, to add context variables to log records.
13+
6. add `queue` arg to `morebuiltins.logs.LogHelper.bind_handler`, to enable async logging with `AsyncQueueListener`. (like loguru's queue=True)
1314

1415
### 1.3.1 (2025-06-19)
1516
1. add `check_recursion` to `morebuiltins.funcs`, to check if a function is recursive.

morebuiltins/logs.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import atexit
23
import logging
34
import re
45
import sys
@@ -60,7 +61,7 @@ class LogHelper:
6061
FILENAME_HANDLER_MAP: Dict[str, logging.Handler] = {}
6162

6263
@classmethod
63-
def close_all_handlers(cls):
64+
def close_all_handlers(cls) -> List[Tuple[str, bool, Optional[Exception]]]:
6465
"""Close all handlers in the FILENAME_HANDLER_MAP."""
6566
result: List[Tuple[str, bool, Optional[Exception]]] = []
6667
for key, handler in list(cls.FILENAME_HANDLER_MAP.items()):
@@ -75,7 +76,7 @@ def close_all_handlers(cls):
7576
@classmethod
7677
def bind_handler(
7778
cls,
78-
name="main",
79+
name: Optional[str] = "main",
7980
filename: Union[
8081
TextIO, TextIOBase, None, logging.Handler, str, Path
8182
] = sys.stderr,
@@ -90,6 +91,7 @@ def bind_handler(
9091
formatter: Union[str, logging.Formatter, None] = DEFAULT_FORMAT,
9192
handler_level: Union[None, str, int] = "INFO",
9293
logger_level: Union[None, str, int] = "INFO",
94+
queue: Union[bool, None, Queue, ProcessQueue] = False,
9395
):
9496
"""Bind a logging handler to the specified logger name, with support for file, stream, or custom handler.
9597
This sets up the logger with the desired handler, formatter, and log levels.
@@ -127,6 +129,12 @@ def bind_handler(
127129
2
128130
>>> bool(LogHelper.close_all_handlers() or True)
129131
True
132+
>>> logger = LogHelper.bind_handler(name="mylogger1", queue=True)
133+
>>> logger.handlers[0]
134+
<QueueHandler (NOTSET)>
135+
>>> logger = LogHelper.bind_handler(name="mylogger2", queue=False)
136+
>>> logger.handlers[0]
137+
<StreamHandler <stderr> (INFO)>
130138
"""
131139
logger = logging.getLogger(name)
132140
if filename is None:
@@ -183,6 +191,14 @@ def bind_handler(
183191
handler.setFormatter(formatter)
184192
# Add the handler to the logger
185193
logger.addHandler(handler)
194+
if queue:
195+
if queue is True:
196+
queue = Queue()
197+
elif not isinstance(queue, (Queue, ProcessQueue)):
198+
raise TypeError("queue must be a Queue, ProcessQueue, True, or False")
199+
async_listener = AsyncQueueListener(logger, queue=queue)
200+
async_listener.start()
201+
atexit.register(async_listener.stop)
186202
return logger
187203

188204
@classmethod

0 commit comments

Comments
 (0)