Using the python logging module in a systemd service script

I’ve developed this Python script that uses the logging module to log output. The idea is that it is supposed to output to stdout as well as to a log file.

I start with a basic config by setting the logging level and format:

logging.basicConfig(format='[%(levelname)s] %(asctime)s %(message)s', level=logging.INFO)
logger = logging.getLogger()

Then I add the file handler (in a try block):

logger.addHandler(logging.FileHandler('/var/log/file.log', mode='a'))

The script runs an infinite while loop (e.g. ‘while True:’) until terminated.

When I run this from an active console, it works exactly as anticipated. But if I run it as a systemd service, I get nothing for output. The log file never records anything, and journald never captures any of the standard output.

On the systemd side, I’m running the script as a “simple” service. I’m not using any special parameters for logging. In the past this has worked for me, so I’m not sure why it doesn’t work now. I am running it on Debian 11. I’ve looked through the docs for both python’s logging module and systemd, but a lot of what I’m reading doesn’t seem to answer my question.

Any thoughts, ideas or other suggestions? I’m happy to share more code if that helps.

If you are going to have systemd log your stdout/stderr to the journal you do not need the log file.

This is what I tried that worked on my Fedora 39 system.
debian 11 should be the same.

:  19:25:19   armf39  ~
:  [1] root $ cat /usr/local/bin/logging_service.py
#!/usr/bin/python3
import logging

logging.basicConfig(format='[%(levelname)s] %(asctime)s %(message)s', level=logging.INFO)
logger = logging.getLogger()

logger.info('example service starting')
logger.error('example service error')

:  19:25:27   armf39  ~
: [1] root $ cat /etc/systemd/system/logging_example.service
[Unit]
Description=logging example

[Service]
Type=oneshot
ExecStart=/usr/local/bin/logging_service.py
RemainAfterExit=yes

:  19:25:43   armf39  ~
: [1] root $ systemctl start logging_example

:  19:26:02   armf39  ~
: [1] root $ systemctl status logging_example
● logging_example.service - logging example
     Loaded: loaded (/etc/systemd/system/logging_example.service; static)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: active (exited) since Mon 2023-12-04 19:24:37 GMT; 1min 28s ago
    Process: 3140 ExecStart=/usr/local/bin/logging_service.py (code=exited, status=0/SUCCESS)
   Main PID: 3140 (code=exited, status=0/SUCCESS)
        CPU: 26ms

Dec 04 19:24:37 armf39.chelsea.private systemd[1]: Starting logging_example.service - logging example...
Dec 04 19:24:37 armf39.chelsea.private logging_service.py[3140]: [INFO] 2023-12-04 19:24:37,928 example service starting
Dec 04 19:24:37 armf39.chelsea.private logging_service.py[3140]: [ERROR] 2023-12-04 19:24:37,928 example service error
Dec 04 19:24:37 armf39.chelsea.private systemd[1]: Finished logging_example.service - logging example.

:  19:26:06   armf39  ~
: [1] root $ journalctl -u logging_example
2023-12-04T19:24:37+0000 systemd[1]: Starting logging_example.service - logging example...
2023-12-04T19:24:37+0000 logging_service.py[3140]: [INFO] 2023-12-04 19:24:37,928 example service starting
2023-12-04T19:24:37+0000 logging_service.py[3140]: [ERROR] 2023-12-04 19:24:37,928 example service error
2023-12-04T19:24:37+0000 systemd[1]: Finished logging_example.service - logging example.

:  19:26:18   armf39  ~
: [1] root $