aiologger 能实现真正的异步日志记录,但需显式使用 AsyncFileHandler 并配合 run_in_executor 才规避磁盘 I/O 阻塞;默认 Logger.info() 返回 awaitable,行为取决于 Handler,AsyncFileHandler 通过线程池解耦 I/O,而误用同步 Handler 仍会阻塞事件循环。

直接上结论:aiologger 能实现真正的异步日志记录,但默认配置下它**不会自动规避磁盘 I/O 阻塞**——你得显式启用 AsyncFileHandler 并配合 loop.run_in_executor 才算落地。否则,哪怕用了 aiologger.Logger,底层仍可能在主线程里调用 os.write 或 file.write,一写大日志就卡住协程。
为什么 aiologger 默认不是“非阻塞”的?
aiologger 的核心设计是“协程友好的日志 API”,不是“零阻塞 I/O 引擎”。它的 Logger.info() 确实返回 awaitable,但实际行为取决于 Handler:
-
AsyncStreamHandler(如输出到sys.stdout)基本不阻塞,因为终端写入在多数系统上是缓冲+快速返回的 -
AsyncFileHandler会把写入任务提交给线程池(loop.run_in_executor),这才是真正解耦 I/O 的关键 - 如果你误用了同步的
FileHandler或没配AsyncFileHandler,日志调用仍会同步阻塞事件循环
正确初始化 AsyncFileHandler 的三要素
缺一不可,否则等于白搭:
- 必须用
aiologger.handlers.files.AsyncFileHandler,不是标准库的logging.FileHandler - 初始化时传
mode='a'(追加模式),避免'w'导致每次清空日志 - 确保
loop已存在且未关闭——推荐在asyncio.run()启动后、创建 logger 前显式获取:asyncio.get_running_loop()
示例:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
import asyncio
from aiologger.logger import Logger
from aiologger.handlers.files import AsyncFileHandler
<p>async def main():
loop = asyncio.get_running_loop()
logger = Logger.with_default_handlers(name="myapp")</p><h1>替换默认 handler 为异步文件 handler</h1><pre class="brush:php;toolbar:false;">logger.remove_handler(logger.handlers[0])
handler = AsyncFileHandler(
filename="/tmp/app.log",
mode="a",
loop=loop
)
logger.add_handler(handler)
await logger.info("This goes to file without blocking loop")
await logger.shutdown()asyncio.run(main())
性能陷阱:批量日志 + 小文件 I/O = 反效果
高频小日志(比如每毫秒一条)走 AsyncFileHandler,反而比同步写更慢——因为每次写都触发一次线程池调度+系统调用。这时应该:
- 用
BufferingAsyncHandler(需自行封装或基于aiologgerv0.8+ 的AsyncTimedRotatingFileHandler的 buffer 机制)做内存缓冲 - 或改用
aiologger+structlog+ujson序列化,减少单条日志体积 - 极端场景(如风控审计日志)直接投递到
redis或kafka,由独立消费者落盘
注意:AsyncFileHandler 不自带缓冲,flush() 是同步调用,别在 await logger.info() 后手动 await handler.flush()——它不支持 await。
真正难的是权衡:异步日志不是开个开关就完事,得看你的日志频率、单条大小、落盘可靠性要求。比如 HTTP 请求 trace 日志,用 AsyncFileHandler 没问题;但高频指标打点,就得绕过文件直连消息队列。


















