Python 的 print 函数在 Docker 中没有输出

0. 问题

在 Docker 容器中运行 Python 写的 HTTPServer 时,发现 print 函数没有输出,但能正常输出 log 信息(例如1.1.1.1 - - [26/Feb/2025 14:31:53] "GET /some/path/ HTTP/1.0" 200 -)。

1. 解决方法

1.1 解决方法1-使用 print 的 flush 参数

仅需要将 print 函数的 flush 参数设置为 True 即可。

1
print('Hello, World!', flush=True)

1.2 解决方法2-添加环境变量 PYTHONUNBUFFERED

在 Dockerfile 中添加环境变量 PYTHONUNBUFFERED,并设置为 1

1
ENV PYTHONUNBUFFERED=1

2. 原因

2.1 为什么 print 没有输出

在 Python 中,print 函数默认是输出到stdout,而 Python 在非交互环境(如 Docker 容器)中默认使用块缓冲模式,只有当缓冲区满或程序结束时才会输出。

Python docs 中对 sys.stdout 的说明如下:

When interactive, the stdout stream is line-buffered. Otherwise, it is block-buffered like regular text files. The stderr stream is line-buffered in both cases. You can make both streams unbuffered by passing the -u command-line option or setting the PYTHONUNBUFFERED environment variable.

可以使用以下代码来模拟这种情况:

1
2
3
4
5
6
7
8
9
10
import sys
import time

buffer_size = 8192 # 假设缓冲区大小为 8192 字节

# 逐字节填充缓冲区
for i in range(1, 3 * buffer_size + 2):
sys.stdout.write("A")
time.sleep(0.001)

在 Docker 容器中运行该代码:

1
docker run --rm python:latest python3 test.py

在本问题中,print 没有输出的原因是缓冲区未满。

2.2 为什么 log 信息能输出

在 Python 中,logging 模块默认是输出到stderr,而 stderr 是行缓冲的,所以 log 信息能够正常输出。

3. 参考


Python 的 print 函数在 Docker 中没有输出
https://nacldragon.top/2025/python-in-docker/
作者
NaCl
发布于
2025年2月26日
许可协议