Featured Image - Set up your Raspberry Pi to Start Python Script on Boot Startup

Posted on

by

in

Set up your Raspberry Pi to Start Python Script on Boot/Startup

Introduction

So you have finished programming your awesome Python Internet of Things (IoT) application and it is working as expected. But you are wondering how I can configure my Raspberry Pi to start your Python script during boot or startup? This post will show you how you can configure your raspberry pi to start your Python script and Flask web app on boot using the systemd command.

If you want to see a demo of this post in video format then please see below or watch it on my YouTube channel.

The Usual Questions

This post will try to answer the following questions that I often receive or see on my blogs:

  • How can I auto-start my Python script when my Raspberry Pi boot?
  • How can I run my Python script on a startup of my Raspberry Pi?
  • How can I run my Python script in a daemon thread on my Raspberry Pi when it starts?
  • How can I run my Python script in a background thread on my Raspberry Pi when it boots?

They may be worded differently but they are almost the same and I would try to answer those questions by using the Raspberry Pi component Linux component called systemd in this post.

What is systemd in Raspberry Pi?

The systemd is an init system commonly used nowadays on most Linux distributions including your Raspberry Pi. An init system is the first program being run by your Linux kernel to run the different services in parallel, initialize the devices attached to your system, and configure the network interfaces of your Raspberry Pi. I find this article to be really good to understand what an init system does and how to configure systemd.

This suite of software is native to the Linux operating system and will allow you to configure the different services, devices, and configurations of your Linux devices. We will use the systemd in this post to configure our Raspberry Pi to start our Python script automatically when it boots.

In fact, when I ask ChatGPT to answer this question for me, it gave me this response. (Note: Yours may be different!)

via GIPHY

What other options do I have apart from the systemd?

When you google how you can run your Python script during the start-up of your Raspberry Pi, you would often be given several options including the following:

  • Edit your /etc/rc.local and add your Python Script
  • Edit your .bashrc file and add your Python Script
  • Edit your /etc/init.d and add your Python Script
  • Create an entry to your crontab

Personally, I don’t like doing the following options as editing some of these startup scripts may affect your bootup process, especially if your Python script throws an exception so I am suggesting using systemd.

Now so much for theory and let us go into accomplishing the goal of this post.

How to run Python script on the startup of your Raspberry Pi using systemd?

Let us use the following sample Raspberry Pi LED – Blink program that will blink an LED connected to your Raspberry Pi. Execute the below command.

mkdir -p Projects/led-blink/
cd led-blink
nano blink.py

After which, place the following sample program.

# Blink an LED using your Raspberry Pi

import RPi.GPIO as GPIO
from time import sleep

led_pin = 11

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(led_pin, GPIO.OUT, initial=GPIO.LOW)

while True:
 GPIO.output(led_pin, GPIO.HIGH)
 sleep(1)
 GPIO.output(led_pin, GPIO.LOW)
 sleep(1)

Run the following program by executing the following command.

python blink.py

You should be able to see the LED connected to your Raspberry Pi blink continuously.

Execute Python Script in the background

Noticed that if you pressed Ctrl + C (or cancel) then your blink.py program would stop running. If you just wanted the LED to blink and ran your Python script in the background then try executing the below command.

python blink.py &

This would direct your script to run in the background. If this is all you want then this solution is ok. However, what if you want your blinking LED program to execute when you reboot your Raspberry Pi? That is where we will use systemd. Let us get on with it.

How to create a systemd unit file?

The systemd init system is using the unit file to know what application or service you want to run during the boot or startup of your Raspberry Pi.

A unit file is nothing more than a text file with special sections and key-value pairs. Start by creating the following file in the following directory /etc/systemd/system. We will name our service as led-blink.service

sudo nano /etc/systemd/system/led-blink.service

Inside the led-blink.service, type in the following information.

[Unit]
Description=Blink LED
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/Projects/led-blink
ExecStart=python blink.py
Restart=always

[Install]
WantedBy=multi-user.target

The important part is in the Service section of my unit file where we set the WorkingDirectory, the User, and the ExecStart key. In our case, we want to execute the following command python blink.py. Take note that you need to supply the full path of all the executables that you wanted to execute here.

You can also configure our service to run once the network is up like the After key in the Unit section. There are other configurations that you can set like setting up the dependency but that is beyond the scope of this post. For now, just follow the following setup but if you want to learn more then please see this post.

Save the file by typing Ctrl-O and exit the nano editor using Ctrl-X.

Next, you need to tell your Raspberry Pi that you have added this new service file by executing the below code.

sudo systemctl daemon-reload

Lastly, you can enable this program to start at boot or during the startup of your Raspberry Pi by executing the below code.

sudo systemctl enable led-blink.service

You would see the following message displayed on your terminal.

pi@raspberrypi4:~/Projects/led-blink $ sudo systemctl enable led-blink.service
Created symlink /etc/systemd/system/multi-user.target.wants/led-blink.service → /etc/systemd/system/led-blink.service.

Reboot your Raspberry Pi afterward and you should be seeing your LED blinking as it should start your Python script on boot.

sudo reboot

How to check the status of your service using systemd?

If you want to check the status of your service or application then execute the code below.

sudo systemctl status led-blink.service

This should output the following messages. If it is active then it means that your Python program is being run successfully and your LED should be blinking continuously.

● led-blink.service - Blink LED
     Loaded: loaded (/etc/systemd/system/led-blink.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-05-30 21:58:04 PST; 23h ago
   Main PID: 567 (python)
      Tasks: 1 (limit: 3933)
        CPU: 2.389s
     CGroup: /system.slice/led-blink.service
             └─567 python blink.py

How to manually start your Python script using systemd?

To manually start your Python script then execute the following command.

sudo systemctl start led-blink.service

How to manually stop your Python script using systemd?

If you wanted to manually stop your Python script from executing then you could type the below command.

sudo systemctl stop led-blink.service

How to disable your Python script from running on boot using systemd?

On the other hand, if you want to manually stop your Python script from executing during the boot or start-up process of your Raspberry Pi then execute the below command.

sudo systemctl disable led-blink.service

How do you auto-start a Python Flask application with a virtual environment during the startup or boot of your Raspberry Pi using systemd?

Using Python virtual environment in your projects is an excellent way to separate the dependencies between your projects. If you wanted your Python application that uses a virtual environment to run during your Raspberry Pi boot or startup then you can use systemd also for this.

In this section, we will deploy our DHT22 Weather Station dashboard Python web application that displays a real-time display of sensor readings which uses the Flask web framework. For details on how this project works then please see the below posts.

Related Content:
Raspberry Pi DHT22 Weather Station Project
Raspberry Pi IoT Weather Station

Web - DHT22 Weather Station Project
Web – DHT22 Weather Station Project

Make sure that you have done all the prerequisites for that project before proceeding further, especially installing the AdaFruit CircuitPython DHT22 library. Please see the following post for reference.

Setup the project

Follow the steps below to install this project on your Raspberry Pi.

  1. Clone the repository
git clone https://github.com/donskytech/dht22-weather-station-python-flask-socketio.git
cd dht22-weather-station-python-flask-socketio
  1. Create a Python virtual environment
python -m venv .venv
source .venv/bin/activate
  1. Install the dependencies
pip install -r requirements.txt
  1. You can now begin running the application using the Flask development server using the below command.
flask run --host=0.0.0.0

After which, you can now access the application using the URL below.

http://<Raspberry-Pi-IP>:5000

However, using the Flask development server for testing and development might be good but if you are going to deploy it to a production environment then you can use the gunicorn Python WSGI HTTP server.

  1. Install gunicorn using the below command if it is not yet installed.
pip install gunicorn

We can now begin running the application using the below command

gunicorn -b 0.0.0.0:5000 -w 2 app:app

You can now begin accessing the same IP address above to view the web application. Right now it using the gunicorn HTTP server to serve our web application which is much better and scalable compared to using the Flask Development Server.

Setup the systemd unit file for a Python Flask Application

We will follow the same procedure above in creating a unit file for our Python Flask Application. Create the following systemd unit file.

sudo nano /etc/systemd/system/dht-weather-station.service

Paste the following information.

[Unit]
Description=DHT22 IoT Weather Station
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/Projects/dht22-weather-station-python-flask-socketio
ExecStart=/home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/gunicorn -b 0.0.0.0:5000 -w 2 app:app
Restart=always

[Install]
WantedBy=multi-user.target

Let us tell our Raspberry Pi system about this new service by reloading it.

sudo systemctl daemon-reload

Now let us try manually starting the service

sudo systemctl start dht-weather-station.service

Check the status of the Flask application.


$ sudo systemctl status dht-weather-station.service
● dht-weather-station.service - DHT22 IoT Weather Station
     Loaded: loaded (/etc/systemd/system/dht-weather-station.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-06-01 16:50:51 PST; 42s ago
   Main PID: 4954 (gunicorn)
      Tasks: 6 (limit: 3933)
        CPU: 10.652s
     CGroup: /system.slice/dht-weather-station.service
             ├─4954 /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/python /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/gunicorn -b 0.0.0.0:5000 -w 2 app:app
             ├─4960 /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/python /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/gunicorn -b 0.0.0.0:5000 -w 2 app:app
             ├─4961 /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/lib/python3.9/site-packages/adafruit_blinka/microcontroller/bcm283x/pulseio/libgpiod_pulsein64 --pulses 81 --queue 26373 -i gpiochip0 3
             └─4963 /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/python /home/pi/Projects/dht22-weather-station-python-flask-socketio/.venv/bin/gunicorn -b 0.0.0.0:5000 -w 2 app:app

If everything is okay then we can enable this service to start during the reboot of our Raspberry Pi.

sudo systemctl enable dht-weather-station.service
Created symlink /etc/systemd/system/multi-user.target.wants/dht-weather-station.service → /etc/systemd/system/dht-weather-station.service.

Try rebooting your Raspberry Pi and verify that it will start our Python Flask web application script on boot.

sudo reboot

How to view logs of applications/services configured using systemd?

If your Python application such as my Flask DHT Weather Station logs information then you can use the journalctl utility command to scan the logs collected by the journald daemon. The journald gathers all the logs coming from all systemd units on your system.

journalctl -u dht-weather-station

If you want to follow the logs from your application then you can execute the following command.

journalctl -u dht-weather-station -f

Wrap Up

In this post, we have discussed how we can use the systemd software suite of your Raspberry Pi to auto-start our Python script during its start-up or boot. I have shown you how to configure your own systemd unit file that will enable your Python application to run when you restart your Raspberry Pi. Also, I have shown you how you can run your Flask web applications that use virtual environments using the same systemd unit configuration file.

I hope you learned something! Happy exploring!

If you like my post then please consider sharing this. Thanks!

5 responses to “Set up your Raspberry Pi to Start Python Script on Boot/Startup”

  1. Raspberry Pi DHT22 Weather Station Project – donskytech.com

    […] Related Content: Set up your Raspberry Pi to Start Python Script on Boot/Startup […]

  2. Bruce Wayne Avatar
    Bruce Wayne

    Love the new auto start addition to the script. Thanks. Is there a place in the code where we can change the values to either display temperature in Fahrenheit or Celsius or have it display both values?

    1. donsky Avatar
      donsky

      Thanks!
      It is quite possible but you need to edit the HTML pages, the javascript that receives the readings, and the dht_module.py class to return multiple values.

  3. Bruce Wayne Avatar
    Bruce Wayne

    Good morning donsky, again thank you for explaining how to get the project to work from boot. But I am now seeing a significant slow response in the readings from the DHT22’s. Prior to this as soon as the page loaded, the sensors would start outputting reading from the sensors, now they are very slow, having to refresh the page a few times and that after the page has been up for a while. The code remained the same except adding the following, pip install gunicorn. What do u think is causing this?

  4. Mark Anthony Avatar
    Mark Anthony

    Hi donsky,
    thanks for the awesome projects by the way. Very easy to follow and very practical in everyday HomeLab and do it yourselfers. I did like how you explained how to get the script to always automatically start on boot of the raspberry pi. I did have the previous version running and I have to say it was much more responsive. Now that I have implemented the pip install gunicorn command the response time from the GUI has significantly slowed down. It is almost as if the sensors aren’t being read by the program and when they do read the refresh rate is not real time 3 to 5 second refresh time. Is there something I can do to fix the issue?

Leave a Reply

Your email address will not be published. Required fields are marked *