首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python应用程序在docker中运行时不会打印任何内容。

Python应用程序在docker中运行时不会打印任何内容。
EN

Stack Overflow用户
提问于 2015-04-16 00:47:16
回答 13查看 153.3K关注 0票数 290

我有一个Python (2.7)应用程序,它在我的dockerfile中启动:

代码语言:javascript
运行
复制
CMD ["python","main.py"]

main.py在启动时打印一些字符串,然后进入循环:

代码语言:javascript
运行
复制
print "App started"
while True:
    time.sleep(1)

只要我使用-it标志启动容器,一切就会如愿以偿:

代码语言:javascript
运行
复制
$ docker run --name=myapp -it myappimage
> App started

稍后我可以通过日志看到相同的输出:

代码语言:javascript
运行
复制
$ docker logs myapp
> App started

如果我尝试使用-d标志运行同一个容器,容器似乎正常启动,但我看不到任何输出:

代码语言:javascript
运行
复制
$ docker run --name=myapp -d myappimage
> b82db1120fee5f92c80000f30f6bdc84e068bafa32738ab7adb47e641b19b4d1
$ docker logs myapp
$ (empty)

但集装箱似乎仍在运行;

代码语言:javascript
运行
复制
$ docker ps
Container Status ...
myapp     up 4 minutes ... 

附件也不显示任何内容:

代码语言:javascript
运行
复制
$ docker attach --sig-proxy=false myapp
(working, no output)

有什么问题吗?在后台运行时,“打印”的行为会有所不同吗?

码头版本:

代码语言:javascript
运行
复制
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.2
Git commit (client): a8a31ef
OS/Arch (client): linux/arm
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.2
Git commit (server): a8a31ef
EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2015-04-20 10:37:19

最后,我找到了一个在Docker中运行守护进程时查看Python输出的解决方案,这要感谢GitHub上的@ahmetalpbalkan。本人在此作答,以供进一步参考:

使用未缓冲的输出

代码语言:javascript
运行
复制
CMD ["python","-u","main.py"]

而不是

代码语言:javascript
运行
复制
CMD ["python","main.py"]

解决问题;您可以通过以下方式看到输出(包括stderr和stdout)

代码语言:javascript
运行
复制
docker logs myapp

现在!

票数 494
EN

Stack Overflow用户

发布于 2015-08-03 20:38:02

在我的例子中,使用-u运行Python并没有改变任何事情。然而,诀窍是将PYTHONUNBUFFERED=1设置为环境变量:

代码语言:javascript
运行
复制
docker run --name=myapp -e PYTHONUNBUFFERED=1 -d myappimage

编辑:在Lars的评论之后,将PYTHONUNBUFFERED=0更新为PYTHONUNBUFFERED=1。这不会改变行为,也不会增加清晰度。

票数 140
EN

Stack Overflow用户

发布于 2019-09-05 08:55:48

请参阅这篇文章,它解释了行为的详细原因:

通常有三种缓冲模式:

  • 如果文件描述符未被缓冲,则不会发生任何缓冲,并且会立即发生读取或写入数据的函数调用(并将阻止)。
  • 如果一个文件描述符是完全缓冲的,那么使用一个固定大小的缓冲区,并且读或写调用简单地从缓冲区读或写。直到缓冲区满了,缓冲区才会被冲洗。
  • 如果文件描述符是行缓冲的,则缓冲区等待直到它看到换行符。因此,数据将缓冲和缓冲,直到看到\n,然后所有缓冲的数据在那个时间点被刷新。实际上,缓冲区上通常有一个最大大小(就像在完全缓冲的情况下一样),因此这个规则实际上更像是“缓冲区,直到看到换行符或遇到4096字节的数据,以先发生者为准”。

GNU libc (glibc)使用以下规则进行缓冲:

代码语言:javascript
运行
复制
Stream               Type          Behavior
stdin                input         line-buffered
stdout (TTY)         output        line-buffered
stdout (not a TTY)   output        fully-buffered
stderr               output        unbuffered

因此,如果使用-t,在码头文件中,它将分配一个伪tty,然后stdout变成line-buffered,因此docker run --name=myapp -it myappimage可以看到一行输出。

而且,如果只使用-d,则没有分配tty,那么,stdoutfully-buffered,一行App started肯定无法刷新缓冲区。

然后,使用-dtmake stdout line buffered或者在python中添加-uflush the buffer是修复它的方法。

票数 34
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29663459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档