You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose运行含asyncio.sleep的Python代码时打印异常求助

问题

我一直绞尽脑汁解决这个看似奇怪的问题。请参考这段Python代码:

import asyncio

async def main():
    print("hello")
    await asyncio.sleep(10)
    print("world")

asyncio.run(main())

我希望将其作为Docker Compose服务运行,以下是我的Dockerfile:

FROM python:3.12-slim

WORKDIR /app
COPY ./main.py /app

CMD ["python", "main.py"]

docker-compose.yaml内容如下:

version: "3.9"
services: 
  dnsgen:
    build: ./dnsgen

现在问题来了:当我执行docker compose up dnsgen --build --timestamps时,两个打印内容会在等待10秒后同时输出:

dnsgen-1  | 2024-02-04T01:16:25.341721172+01:00hello
dnsgen-1  | 2024-02-04T01:16:25.341784837+01:00world

但在本地直接运行python main.py,或是执行docker compose run dnsgen时,都不会出现这个问题。

原因与解决办法

这是Python标准输出缓冲机制导致的差异:

  • 当Python运行在非交互式终端环境(比如docker compose up的日志捕获模式),标准输出默认启用块缓冲——print("hello")的内容会被暂存到缓冲区,直到程序结束、缓冲区满或显式刷新时才会一次性输出。
  • 而docker compose run或本地直接运行时,终端是交互式的,Python会使用行缓冲,print的内容会立即输出到终端。

解决办法有两种:

方法一:通过Python参数禁用缓冲

修改Dockerfile中的CMD命令,添加-u参数强制Python使用无缓冲的标准流:

CMD ["python", "-u", "main.py"]

方法二:在代码中显式刷新缓冲区

修改print语句,添加flush=True参数,每次打印后立即刷新缓冲区:

import asyncio

async def main():
    print("hello", flush=True)
    await asyncio.sleep(10)
    print("world", flush=True)

asyncio.run(main())

两种方案都能解决docker compose up下日志延迟输出的问题:方法一针对容器运行环境配置,方法二让代码在任何环境下都能即时输出。

内容的提问来源于stack exchange,提问作者elaich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:18:18