Python Script as a Reliable Service

Andrew Bolster

Senior R&D Manager (Data Science) at Black Duck Software and Treasurer @ Bsides Belfast and NI OpenGovernment Network

I was asked to help out a friend who had an installation in an art gallery that stopped booting properly, and was reminded that I keep forgetting to actually write this post.

Running a python script as a reliable, retryable service on a Raspberry Pi that waits for an ‘up’ network connection, because I’m an idiot who keeps changing his mind how to do it.

Fail gracefully and with informative error messages:

try: ... except:... is your friend

Use the logging library by default

import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug('This will get logged')

OR

import logging

logging.basicConfig(filename='app.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will get logged to a file')

Just use Systemd, don’t get religious

$EDITOR /lib/systemd/system/awesome.service

[Unit]
Description=My Awesome Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/python /home/pi/my_awesome_service.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

sudo chmod 644 /lib/systemd/system/awesome.service

chmod +x /home/pi/my_awesome_service.py

sudo systemctl daemon-reload

sudo systemctl enable awesome.service

sudo systemctl start awesome.service

sudo systemctl status awesome.service -l

Then test it by rebooting repeatedly until you develop any kind of confidence in yourself.

Note: The Restart=on-failure will not restart the service if it cleanly exits, like sys.exit(0), and RestartSec=10 will wait for 10 seconds before relaunching the service, which will prevent the service being permenantly killed if by the interval handler.

Sources:

blog comments powered by Disqus