6

I have a Python script which ideally runs indefinitely in a loop. I am catching some exceptions, however, the problem is when some error occurs and the script stops because of that error. I want to detect somehow this situation and restart the script.

As I have some logic with time inside script, I don't see an option with another script running a sub-process script as a good one.

tripleee
  • 128
  • 1
  • 8
PostarLakogSna
  • 91
  • 1
  • 1
  • 9
  • 1
    What error is occurring that stops your script? Why can't you catch it? – CoderMike Oct 26 '19 at 11:55
  • 3
    You can do this putting your instructions in a while loop. while True: , and use exception KeyboardInterrupt for exiting while loop when you press [CTRL+C]. You can also use a system unit file for starting your python script, the file can contain : Restart, Timeout etc ... (I think it's the best method). You can see the options here – Ephemeral Oct 26 '19 at 12:06
  • 1
    It communicates with google sheets api and usually error occurs there. As it is important that it has almost 99 percent running time I would like to ensure that it restarts – PostarLakogSna Oct 26 '19 at 12:09
  • 1
    @PostarLakogSna, google not provide any exception handler for your error ? Have you try to put a global try: Except for getting your error description ? – Ephemeral Oct 26 '19 at 12:28
  • 2
    Correction: (I think it's the best method) ... no the best method is to check the errors correctly first and then maybe use a system unit file. – Ephemeral Oct 26 '19 at 12:30
  • 1
    I did try putting general except, but sometimes scrpt still exits. In my oppinion rerun is the best way – PostarLakogSna Oct 26 '19 at 12:31
  • 1
    @PostarLakogSna, if you want a template for unit file (but you must add restart = always and timeout parameters) and the systems commands for enable this you can check my answer here, put : python /home/pi/yourfile.py in ExecStart – Ephemeral Oct 26 '19 at 12:42

3 Answers3

6

You can run the script as service using systemd. Just create a Unit file with:

rpi ~$ sudo systemctl --force --full edit myscript.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=My Python Script
After=multi-user.target

[Service] RestartSec=10 Restart=always ExecStart=python3 /full/path/to/myscript.py

[Install] WantedBy=multi-user.target

This will always restart your script after 10 seconds. Always restarting a script may not be the best option if it should terminate regular. You can use the settings no, on-success, on-failure, on-abnormal, on-watchdog, on-abort or always. There are many other options to restart the script as you can find in man systemd.service.

Enable and run the service with

rpi ~$ sudo systemctl enable --now myscript.service

Check it with

rpi ~$ systemctl status myscript.service
Ingo
  • 42,107
  • 20
  • 85
  • 197
2

Consider using the continue statement to restart the while loop if you can detect the error with an "if" statement:

while True:
    <all your code>

    if <some error occurs>:
         time.sleep(10)
         continue

The continue statement will bring control back to the top of your while loop

user3217032
  • 101
  • 1
  • 5
  • 1
    You don't need that continue instruction at all as long as try is in the right scope (which is the highest scope in the while loop, like you correctly did) – Sim Son Oct 26 '19 at 20:14
  • You should throw a delay in there of at least a few seconds so a problem with the code failing immediately does not lead to busy looping. – goldilocks Oct 27 '19 at 13:21
0

For error handling you can use Try-Except https://www.w3schools.com/python/python_try_except.asp . That way you decide what to do with every error or exception (so you basically MUST decide every time).

Your code would have to be very well structured (even with lots of try-excepts) in order to "catch them all", but that's something worth working on.

Clóvis Fritzen
  • 373
  • 1
  • 11