Python 3 app 运行 in docker-compose 将不会使用 print('text', end='\r') 打印
Python 3 app running in docker-compose will not print using print('text', end='\r')
希望得到有关 解决方法 或 修复 的建议:
Python 3.9 运行 在 docker-compose 3.8 中使用 CMD [ "python3", "-u", "app.py" ]
print('text', end='\r', flush=True)
将 不会 打印到终端 - 希望打印出来。
print('text', flush=True)
将打印到终端。
是的,同时使用"python3", "-u"
和flush=True
有点过分了。♂️
print()
函数将打印消息中的所有字符,然后在打印后附加结束字符。如果你省略 end=
它默认为换行符(\n
在 nix 上)。 \r
字符将光标移动到 相同 行的开头。
所以让我们看一下 python 解释器中的几种情况:
# print 'text' followed by \r (move to beginning of line) followed by newline
>>> print('text\r')
asdf
>>>
在这个例子中,打印text
,然后光标移动到同一行的开头,然后打印默认的换行符移动到下一行。最后,python 打印其提示。
# print 'text' followed by \r followed by nothing
>>> print('text', end='\r')
>>>
在这个例子中,打印了text
,光标移动到同一行的开头,然后命令结束,解释器打印提示>>>
覆盖text
已打印。
# print 'text followed by \r followed by nothing (alternate)
>>> print ('text\r', end='')
>>>
以上与前面的例子相同
当您从终端使用 python 运行 脚本时,情况非常相似,除了 python 解释器打印提示外,您的 shell 是程序执行后打印提示。
很难在此处提出“修复”建议,因为不清楚您实际想要完成什么。
我认为你只需要在前面加上 \r
,例如:
import time
for i in range(10):
print('\rcount {}'.format(i), end='')
time.sleep(1)
在这里您会看到消息 count n
,每秒都在变化。
docker-compose up
的输出聚合 1 并且有效地 line-buffered 2 (参见 示例日志),这意味着它仅在看到 \n
时打印。关于此行为还有其他轶事 3,4 \r
。
可以看到其实是运行 docker-compose run app
5.
打印的
参考文献:
- https://docs.docker.com/compose/reference/up/
- https://eklitzke.org/stdout-buffering
- https://github.com/docker/compose/issues/1549#issuecomment-745086053
- https://docs.docker.com/compose/faq/#whats-the-difference-between-up-run-and-start
解决方法
1。 运行直接单个应用
运行docker-compose run app
,如上所述。
docker-compose run
的输出直接进入终端的标准输出。
2。将输出复制到 volume-mounted 文件并观看
tee
CMD
中的输出到已安装卷中的文件,然后 tail -F
该文件。
touch app.log
docker-compose up & tail -F app.log
(Ctrl+C 退出 tail -F app.log
。)
示例文件
app.py:
from time import sleep
for i in range(10):
print('text: {}'.format(i), end='\r')
sleep(0.3)
Dockerfile:
FROM python:3.7-alpine
WORKDIR /app
COPY . .
# CMD [ "python3", "-u", "app.py" ]
CMD python3 -u app.py > app.log
docker-compose.yml:
version: "3.9"
services:
app:
build: .
volumes:
- ./:/app
示例日志
来自 docker-compose up
无解决方法:
==> /var/lib/docker/containers/xxx/xxx-json.log <==
{"log":"text: 0\rtext: 1\rtext: 2\rtext: 3\rtext: 4\rtext: 5\rtext: 6\rtext: 7\rtext: 8\rtext: 9\r","stream":"stdout","time":"xxx"}
因此,print('text: 0\rtext: 1\rtext: 2\rtext: 3\rtext: 4\rtext: 5\rtext: 6\rtext: 7\rtext: 8\rtext: 9\r')
有效地打印了 text: 9\r
.
如何在 macOS 中查看日志
- 使用
nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock
在 VM 中打开一个 shell。
参考:https://docs.docker.com/desktop/mac/release-notes/2.x/#docker-desktop-community-2400
- 运行
tail /var/lib/docker/containers/*/*.log
.
希望得到有关 解决方法 或 修复 的建议:
Python 3.9 运行 在 docker-compose 3.8 中使用 CMD [ "python3", "-u", "app.py" ]
print('text', end='\r', flush=True)
将 不会 打印到终端 - 希望打印出来。
print('text', flush=True)
将打印到终端。
是的,同时使用"python3", "-u"
和flush=True
有点过分了。♂️
print()
函数将打印消息中的所有字符,然后在打印后附加结束字符。如果你省略 end=
它默认为换行符(\n
在 nix 上)。 \r
字符将光标移动到 相同 行的开头。
所以让我们看一下 python 解释器中的几种情况:
# print 'text' followed by \r (move to beginning of line) followed by newline
>>> print('text\r')
asdf
>>>
在这个例子中,打印text
,然后光标移动到同一行的开头,然后打印默认的换行符移动到下一行。最后,python 打印其提示。
# print 'text' followed by \r followed by nothing
>>> print('text', end='\r')
>>>
在这个例子中,打印了text
,光标移动到同一行的开头,然后命令结束,解释器打印提示>>>
覆盖text
已打印。
# print 'text followed by \r followed by nothing (alternate)
>>> print ('text\r', end='')
>>>
以上与前面的例子相同
当您从终端使用 python 运行 脚本时,情况非常相似,除了 python 解释器打印提示外,您的 shell 是程序执行后打印提示。
很难在此处提出“修复”建议,因为不清楚您实际想要完成什么。
我认为你只需要在前面加上 \r
,例如:
import time
for i in range(10):
print('\rcount {}'.format(i), end='')
time.sleep(1)
在这里您会看到消息 count n
,每秒都在变化。
docker-compose up
的输出聚合 1 并且有效地 line-buffered 2 (参见 示例日志),这意味着它仅在看到 \n
时打印。关于此行为还有其他轶事 3,4 \r
。
可以看到其实是运行 docker-compose run app
5.
参考文献:
- https://docs.docker.com/compose/reference/up/
- https://eklitzke.org/stdout-buffering
- https://github.com/docker/compose/issues/1549#issuecomment-745086053
- https://docs.docker.com/compose/faq/#whats-the-difference-between-up-run-and-start
解决方法
1。 运行直接单个应用
运行docker-compose run app
,如上所述。
docker-compose run
的输出直接进入终端的标准输出。
2。将输出复制到 volume-mounted 文件并观看
tee
CMD
中的输出到已安装卷中的文件,然后 tail -F
该文件。
touch app.log
docker-compose up & tail -F app.log
(Ctrl+C 退出 tail -F app.log
。)
示例文件
app.py:
from time import sleep
for i in range(10):
print('text: {}'.format(i), end='\r')
sleep(0.3)
Dockerfile:
FROM python:3.7-alpine
WORKDIR /app
COPY . .
# CMD [ "python3", "-u", "app.py" ]
CMD python3 -u app.py > app.log
docker-compose.yml:
version: "3.9"
services:
app:
build: .
volumes:
- ./:/app
示例日志
来自 docker-compose up
无解决方法:
==> /var/lib/docker/containers/xxx/xxx-json.log <==
{"log":"text: 0\rtext: 1\rtext: 2\rtext: 3\rtext: 4\rtext: 5\rtext: 6\rtext: 7\rtext: 8\rtext: 9\r","stream":"stdout","time":"xxx"}
因此,print('text: 0\rtext: 1\rtext: 2\rtext: 3\rtext: 4\rtext: 5\rtext: 6\rtext: 7\rtext: 8\rtext: 9\r')
有效地打印了 text: 9\r
.
如何在 macOS 中查看日志
- 使用
nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock
在 VM 中打开一个 shell。
参考:https://docs.docker.com/desktop/mac/release-notes/2.x/#docker-desktop-community-2400 - 运行
tail /var/lib/docker/containers/*/*.log
.