在Docker文件中,PYTHONUNBUFFERED的作用是什么?

268
我正在观看一个关于将我的Django应用程序docker化的教程。我不明白为什么我们在Dockerfile中使用PYTHONUNBUFFERED作为环境变量。
有人能解释一下吗?
3个回答

410

PYTHONUNBUFFERED 设置为非 0 的非空值可以确保 python 输出即 stdoutstderr 流直接发送到终端(例如容器日志),无需先缓冲,并且可以实时查看应用程序的输出(例如 django 日志)。

这还确保了在 python 应用程序崩溃的情况下,没有部分输出被保留在某个缓冲区中并被忽略。

由于这已经在几个评论和补充回答中提到过,请注意 PYTHONUNBUFFERED 对输入(即 stdin 流)完全没有影响。

换句话说,在 docker 容器中关闭 stdout/stderr 的缓冲主要是获取尽可能多的信息并在容器日志中尽快显示运行应用程序的输出,以防止在应用程序崩溃时丢失任何东西。

请注意,关闭缓冲可能会对性能产生影响,具体取决于您的硬件/环境。但大多数情况下影响都不会太大(除非您有较慢的磁盘或正在编写大量日志,或者不好地想要配置 docker 守护程序将日志写入较慢的网络驱动器中...)。如果有这方面的顾虑,可以保留缓冲区并在需要时直接从应用程序刷新缓冲区。有关此主题,请参阅以下第 4 链接。

参考文献:


强制stdout和stderr流不带缓冲区。此选项对stdin流没有影响。另请参阅PYTHONUNBUFFERED。自3.7版本起更改:stdout和stderr流的文本层现在是无缓冲的。 - Louis Huang
3
FYI:设置 PYTHONUNBUFFERED=0 具有与未设置或为空字符串相同的效果。这是因为 CPython 尝试使用 strtol(3)(完全字符串匹配)解析环境变量。 - iBug
Python缓冲难道不是为了优化,以免在每个小的打印单词时等待IO吗?这个选项不应该专门用于开发场景吗? - N1ngu
1
@N1ngu 请记住,我们在谈论在Docker中运行Python。除了上面提供的链接外,我找到了一些关于可能出现的问题的链接。主要问题是如果容器崩溃,需要实时查看日志。你可能可以找到更多相关信息:https://dev59.com/LJrga4cB1Zd3GeqPrb5k http://www.pixelbeat.org/programming/stdio_buffering/ https://github.com/docker/compose/issues/1838 https://serverfault.com/questions/940281/why-doesnt-my-docker-actually-log-anything ... - Zeitounator
也许是因为Docker镜像通常部署在日志被定向到汇聚器(如Kubernetes或OpenShift)的系统上,即使发生崩溃,您也希望在其中获得所有内容。这不是一个论坛,而是一个问答网站。如果您认为这值得提问,请提出一个问题。注意:如果我必须在经典服务器上运行Django,则也会禁用Python输出的缓冲区。您可以自由地按照自己的意愿做,我认为这不应该在这里引起基于观点的讨论。 - Zeitounator
显示剩余2条评论

16
一个非空的PYTHONUNBUFFERED值会强制stdout和stderr流不被缓冲。这个选项对stdin流没有影响。

6

这将指示 Python 以非缓冲模式运行,当在 Docker 容器内使用 Python 时,推荐使用此模式。原因是它不允许 Python 缓冲输出;相反,直接打印输出,避免了运行 Python 应用程序时 Docker 镜像中的某些复杂性。


有什么复杂性吗?我想了解背后的原理,并且希望能够提供一些链接。到目前为止,我担心这是从Django教程中大规模无脑复制粘贴而来。我从未见过在Docker之外进行生产部署使用它。 - N1ngu
3
@N1ngu 我担心这是一个写得太快、没有进行适当的先前研究并包含过早主观(可能会伤害人)对作者技能的判断的评论。在开发或生产中出现应用程序的重大崩溃,而日志中没有任何迹象,可能会成为理解发生了什么的主要障碍。这可以被称为复杂性(即使我同意应该给出细节)。 - Zeitounator
@Zeitounator,那很公平。 - N1ngu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接