如何防止 Docker 弄乱子进程输出顺序? (包括 MCVE)
How to prevent Docker from messing with subprocess output order? (MCVE included)
考虑这个 issue.py
文件:
import subprocess
print('Calling subprocess...')
subprocess.run(['python', '--version'])
print('Subprocess is done!')
手动执行 python issue.py
会产生我期望的结果:
Calling subprocess...
Python 3.9.0
Subprocess is done!
但是,如果我在 Docker 容器中执行此操作,则会发生一些奇怪的事情:
$ docker run --rm -v $(pwd):/issue python:3.9.0 python /issue/issue.py
Python 3.9.0
Calling subprocess...
Subprocess is done!
如何解决这个问题,使 Docker 遵守正确的输出顺序?
备注:
- 这个问题也发生在
stderr
,虽然上面的MCVE没有显示出来。
- MCVE 直接使用
python
图像,但在我的实际用例中,我有一个来自自定义 Docker 文件的自定义图像,该文件使用 FROM python
.
- 在
subprocess.run
调用中使用 capture_output=True
然后打印捕获的输出对我来说不是一个选项,因为我的真实用例调用一个子进程,随着时间的推移将信息打印到 stdout
(不像 python --version
),我等不及它完成后才打印整个输出。
正如@DavidMaze 在评论中指出的那样,我只需要将 PYTHONUNBUFFERED
环境变量设置为 1
。这可以通过以下方式完成:
docker run --rm -e PYTHONUNBUFFERED=1 -v $(pwd):/issue python:3.9.0 python /issue/issue.py
考虑这个 issue.py
文件:
import subprocess
print('Calling subprocess...')
subprocess.run(['python', '--version'])
print('Subprocess is done!')
手动执行 python issue.py
会产生我期望的结果:
Calling subprocess...
Python 3.9.0
Subprocess is done!
但是,如果我在 Docker 容器中执行此操作,则会发生一些奇怪的事情:
$ docker run --rm -v $(pwd):/issue python:3.9.0 python /issue/issue.py
Python 3.9.0
Calling subprocess...
Subprocess is done!
如何解决这个问题,使 Docker 遵守正确的输出顺序?
备注:
- 这个问题也发生在
stderr
,虽然上面的MCVE没有显示出来。 - MCVE 直接使用
python
图像,但在我的实际用例中,我有一个来自自定义 Docker 文件的自定义图像,该文件使用FROM python
. - 在
subprocess.run
调用中使用capture_output=True
然后打印捕获的输出对我来说不是一个选项,因为我的真实用例调用一个子进程,随着时间的推移将信息打印到stdout
(不像python --version
),我等不及它完成后才打印整个输出。
正如@DavidMaze 在评论中指出的那样,我只需要将 PYTHONUNBUFFERED
环境变量设置为 1
。这可以通过以下方式完成:
docker run --rm -e PYTHONUNBUFFERED=1 -v $(pwd):/issue python:3.9.0 python /issue/issue.py