Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker-compose not printing stdout in Python app

When using a print() statement in a Python app running inside a Docker container that's managed by Docker Compose, only sys.stderr output is logged. Vanilla print() statements aren't seen, so this:

print("Hello? Anyone there?") 

... never shows up in the regular logs:

enter image description here

(You can see other logs explicitly printed by other libs in my app, but none of my own calls.)

How can I avoid my print() calls being ignored?

like image 462
Lee Benson Avatar asked Jul 16 '18 12:07

Lee Benson


People also ask

What is stdin and stdout in docker?

In general they are same as what you have mentioned and read in reference links for python. streams for receiving or reading input (stdin) and printing output (stdout). Example input from the keyboard or printing output to unix terminal.

What is Python unbuffered?

Setting PYTHONUNBUFFERED=TRUE or PYTHONUNBUFFERED=1 (they are equivalent) allows for log messages to be immediately dumped to the stream instead of being buffered.

Is Docker Compose deprecated?

Compose V1 is marked as deprecated, and we'll begin patching only high-severity vulnerabilities or fixing critical bugs until the next milestone. Developers can continue to alias docker-compose to use docker compose.


2 Answers

By default, Python buffers output to sys.stdout.

There are a few options:

1. Call an explicit flush

Refactor the original print statement to include a flush=True keyword, like:

print("Hello? Anyone there?", flush=True) 

Note: This will cause the entire buffer to flush, not just the same print call. So if there are 'bare' print function calls elsewhere (i.e. without flush=True) that weren't explicitly unbuffered, these will always be flushed too.

You could achieve the same thing with:

import sys sys.stdout.flush() 

This option is useful if you want the most control of when the flushing will occur.

2. Unbuffer the entire app via the PYTHONUNBUFFERED env var

Drop the following into the environment section of your docker-compose.yml file:

PYTHONUNBUFFERED: 1

This will cause all output to stdout to be flushed immediately.

3. Run python with -u

Like option #2 above, this will cause Python to run 'unbuffered' across the full execution lifetime of your app. Just run with python -u <entrypoint.py> - no need for the environment variable.

like image 109
Lee Benson Avatar answered Oct 02 '22 16:10

Lee Benson


Simple, if you add the option -u in the line of the Dockerfile it will print your logs:

CMD ["python", "-u", "my_python_script.py"] 

No need of changing an environment variable or change all the prints statements of your program.

like image 38
Ignacio Peletier Avatar answered Oct 02 '22 16:10

Ignacio Peletier