Перезапуск скрипта python при ошибке

For something like this (connecting to a web page), it’s often better to make the upper limit based on time instead of the number of times you attempt to connect. So use a while loop instead:

import numpy as np
import time

def main():
    np.load('file.csv')

start = time.time()
stop = start + 5
attempts = 0
result = 'failed'

while True:
    if time.time()<stop:
        try:
            main()
        except Exception as e:
            attempts += 1
            print e
            time.sleep(0.1) # optional
            print 'Restarting!'
            continue
        else:
            result = 'succeeded'
    print 'Connection %s after %i attempts.' % (result, attempts)
    break

Optional: I included a 100 ms pause after each failed attempt. This can help with establishing a connection sometimes.

Then wrap the whole thing up in a function you can use in the future for other projects:

# retry.py

import time

def retry(f, seconds, pause = 0):
    start = time.time()
    stop = start + seconds
    attempts = 0
    result = 'failed'

    while True:
        if time.time()<stop:
            try:
                f()
            except Exception as e:
                attempts += 1
                print e
                time.sleep(pause)
                print 'Restarting!'
                continue
            else:
                result = 'succeeded'
        print '%s after %i attempts.' % (result, attempts)
        break

now just do this:

import numpy as np
from retry import retry

def main():
    np.load('file.csv')

retry(main, 5, 0.1)

Testing procedure:

class RetryTest():
    def __init__(self, succeed_on = 0, excp = Exception()):
        self.succeed_on = succeed_on
        self.attempts = 0
        self.excp = excp
    def __call__(self):
        self.attempts += 1
        if self.succeed_on == self.attempts:
            self.attempts = 0
        else:
            raise self.excp

retry_test1 = RetryTest(3)
retry(retry_test1, 5, 0.1)
# succeeded after 3 attempts.
retry_test2 = RetryTest()
retry(retry_test2, 5, 0.1)
# failed after 50 attempts.

I have a program that queries an API every few seconds. Each response triggers a few functions which themselves make some calls to websites and such — calls that I don’t want to blindly trust to succeed. If I catch an exception in foo(), for example, or even in a function that foo() calls, is it possible to restart the program entirely in the except block? Essentially, I want to call queryRepeatedly() upon an exception in one of its sub-functions, without keeping the previous call on the stack.

Of course, I could return marker values and solve this another way, but the program is structured in a way such that the above approach seems much simpler and cleaner.

# Sample "main" function that I want to call
def queryRepeatedly():
    while True:
        foo()
        bar()
        baz()
        time.sleep(15)

def foo():
    # do something
    try:
        foo2() # makes a urllib2 call that I don't trust
    except:
        #restart queryRepeatedly

queryRepeatedly()

pppery's user avatar

pppery

3,70021 gold badges32 silver badges45 bronze badges

asked Jul 8, 2013 at 18:02

vroomfondel's user avatar

3

To restart anything, just use a while loop outside the try. For example:

def foo():
    while True:
        try:
            foo2()
        except:
            pass
        else:
            break

And if you want to pass the exception up the chain, just do this in the outer function instead of the inner function:

def queryRepeatedly():
    while True:
        while True:
            try:
                foo()
                bar()
                baz()
            except:
                pass
            else:
                break
        time.sleep(15)

def foo():
    foo2()

All that indentation is a little hard to read, but it’s easy to refactor this:

def queryAttempt()
    foo()
    bar()
    baz()

def queryOnce():
    while True:
        try:
            queryAttempt()
        except:
            pass
        else:
            break

def queryRepeatedly():
    while True:
        queryOnce()
        time.sleep(15)

But if you think about it, you can also merge the two while loops into one. The use of continue may be a bit confusing, but see if you like it better:

def queryRepeatedly():
    while True:
        try:
            foo()
            bar()
            baz()
        except:
            continue
        time.sleep(15)

Daniel Walker's user avatar

answered Jul 8, 2013 at 18:05

abarnert's user avatar

abarnertabarnert

352k50 gold badges598 silver badges668 bronze badges

2

Refactor this — you’ll get a stackoverflow error sooner or later if you have enough failures.

queryRepeatedly should just be query. It should return void and throw exceptions on failures.

Wrap in something that looks like this, your true queryRepeatedly function?

while True:
    try:
        query()
    except:
        #handle
    time.sleep(15)

All looping, no recursion needed.

Note that you must think carefully about how much of your program you need to restart. From your question it sounded like your actual problem was ensuring the query could try again if it sporadically fails, which is what my solution ensures. But if you want to clean up program resources — say, bounce SQL connections, which may have broken — then you need to think more carefully about how much of your program you need to «restart.» In general you need to understand why your query failed to know what to fix, and in the extreme case, the right thing to do is an email or SMS to someone on call who can inspect the situation and write an appropriate patch or fix.

answered Jul 8, 2013 at 18:06

djechlin's user avatar

djechlindjechlin

59k34 gold badges161 silver badges288 bronze badges

12

First make two files.

One file called run.py and one called forever.py and put them in the same folder.

Go to your terminal within that folder and type chmod +x forever.py

run.py

whatever code you want to run

forever.py

#!/usr/local/lib/python3.7
from subprocess import Popen
import sys

filename = sys.argv[1]
while True:
    print("nStarting " + filename)
    p = Popen("python3 " + filename, shell=True)
    p.wait()

Open a terminal window from the folder and type this:

python3 ./forever.py run.py

to start run.py and if it fails or has an exception, it’ll just start over again.

You now have a template to make sure if a file crashes or has an exception, you can restart it without being around. If this helps you, please give me a vote!

Olivier's user avatar

answered Mar 1, 2020 at 4:50

Cody Krecicki's user avatar

0

In your exception make a recursive call

except:
      queryRepeatedly()

answered Jul 8, 2013 at 18:06

sedavidw's user avatar

sedavidwsedavidw

11k13 gold badges60 silver badges94 bronze badges

4

Как сделать так чтобы скрипт на питоне при ошибке заново запускался?

Вот у меня есть телеграм бот, и иногда он стопается, мол ошибка (там другая история).
И как сделать так, чтобы скрипт автоматически после остановки запускался заново (python bot.py)?


  • Вопрос задан

    более трёх лет назад

  • 2267 просмотров

while true; do python bot.py; done

Можно с помощью инструкций try/except.

def function():	
	try:
		a = input("Enter a number")
		b = int(a) / 0
	except:
		function()
function()

Поместите туда свой код, при ошибке, функция будет вызвана заново.

Пригласить эксперта


  • Показать ещё
    Загружается…

25 июн. 2023, в 13:53

2000 руб./за проект

25 июн. 2023, в 13:25

500 руб./в час

25 июн. 2023, в 11:42

600 руб./за проект

Минуточку внимания

When the python script crashes, the program is not running anymore, therefore the script cannot execute more lines of code.

You have 2 options:

  1. Make sure your python script doesn’t crash, which is very much recommended. You can do this by handling the exceptions thrown by your program.

Option 1

I assume you are new to python, so here is an example of a python script that handles an exception calls the same function again.

from time import sleep

def run_forever():
    try:
        # Create infinite loop to simulate whatever is running
        # in your program
        while True:
            print("Hello!")
            sleep(10)

            # Simulate an exception which would crash your program
            # if you don't handle it!
            raise Exception("Error simulated!")
    except Exception:
        print("Something crashed your program. Let's restart it")
        run_forever() # Careful.. recursive behavior
        # Recommended to do this instead
        handle_exception()

def handle_exception():
    # code here
    pass

run_forever()
  1. If you want to restart the python script you would need another python script (assuming you want to do this with python) that checks if the process is still alive and if not then run it again with python.

Option 2

This is the script that starts another python script called ‘test.py’ via the command python test.py.
Make sure you have the right file path, if you put the scripts in the same folder, you usually don’t need the full path and only the script name.

Notably, make sure that command ‘python‘ is recognized by your system, it could in some cases by ‘python3’

script_starter.py

from subprocess import run
from time import sleep

# Path and name to the script you are trying to start
file_path = "test.py" 

restart_timer = 2
def start_script():
    try:
        # Make sure 'python' command is available
        run("python "+file_path, check=True) 
    except:
        # Script crashed, lets restart it!
        handle_crash()

def handle_crash():
    sleep(restart_timer)  # Restarts the script after 2 seconds
    start_script()

start_script()

In case you are interested in the code I used for the test file: ‘test.py’, I post it here.

test.py

from time import sleep
while True:
    sleep(1)
    print("Hello")
    raise Exception("Hello")

Как сделать так чтобы скрипт на питоне при ошибке заново запускался?

Вот у меня есть телеграм бот, и иногда он стопается, мол ошибка (там другая история).
И как сделать так, чтобы скрипт автоматически после остановки запускался заново (python bot.py)?


  • Вопрос задан

    более двух лет назад

  • 1754 просмотра

while true; do python bot.py; done

Можно с помощью инструкций try/except.

def function():	
	try:
		a = input("Enter a number")
		b = int(a) / 0
	except:
		function()
function()

Поместите туда свой код, при ошибке, функция будет вызвана заново.

Пригласить эксперта


  • Показать ещё
    Загружается…

29 янв. 2023, в 10:09

2000 руб./за проект

28 янв. 2023, в 13:14

10000 руб./за проект

29 янв. 2023, в 03:07

300000 руб./за проект

Минуточку внимания

This post describes how to keep a child process alive in a BASH script:

How do I write a bash script to restart a process if it dies?

This worked great for calling another BASH script.

However, I tried executing something similar where the child process is a Python script, daemon.py which creates a forked child process which runs in the background:

#!/bin/bash

PYTHON=/usr/bin/python2.6

function myprocess {


$PYTHON daemon.py start

}
NOW=$(date +"%b-%d-%y")

until myprocess; do
     echo "$NOW Prog crashed. Restarting..." >> error.txt
     sleep 1
done

Now the behaviour is completely different. It seems the python script is no longer a child of of the bash script but seems to have ‘taken over’ the BASH scripts PID — so there is no longer a BASH wrapper round the called script…why?

Community's user avatar

asked Apr 26, 2010 at 15:00

chris's user avatar

2

A daemon process double-forks, as the key point of daemonizing itself — so the PID that the parent-process has is of no value (it’s gone away very soon after the child process started).

Therefore, a daemon process should write its PID to a file in a «well-known location» where by convention the parent process knows where to read it from; with this (traditional) approach, the parent process, if it wants to act as a restarting watchdog, can simply read the daemon process’s PID from the well-known location and periodically check if the daemon is still alive, and restart it when needed.

It takes some care in execution, of course (a «stale» PID will stay in the «well known location» file for a while and the parent must take that into account), and there are possible variants (the daemon could emit a «heartbeat» so that the parent can detect not just dead daemons, but also ones that are «stuck forever», e.g. due to a deadlock, since they stop giving their «heartbeat» [[via UDP broadcast or the like]] — etc etc), but that’s the general idea.

answered Apr 26, 2010 at 15:20

Alex Martelli's user avatar

Alex MartelliAlex Martelli

837k165 gold badges1209 silver badges1388 bronze badges

You should look at the Python Enhancement Proposal 3143 (PEP) here. In it Ben suggests including a daemon library in the python standard lib. He goes over LOTS of very good information about daemons and is a pretty easy read. The reference implementation is here.

answered Apr 26, 2010 at 16:10

Paul Hildebrandt's user avatar

1

It seems that the behavior is completely different because here your «daemon.py» is launched in background as a daemon.

In the other link you pointed to the process that is surveyed is not a daemon, it does not start in the background. The launcher simply wait forever that the child process stop.

There is several ways to overcome this. The classical one is the way @Alex explain, using some pid file in conventional places.

Another way could be to build the watchdog inside your running daemon and daemonize the watchdog… this would simulate a correct process that do not break at random (something that shouldn’t occur)…

answered Apr 26, 2010 at 15:20

kriss's user avatar

krisskriss

23.1k17 gold badges97 silver badges115 bronze badges

Make use of ‘https://github.com/ut0mt8/simple-ha’ .

simple-ha

Tired of keepalived, corosync, pacemaker, heartbeat or whatever ? Here a simple daemon wich ensure a Heartbeat between two hosts. One is active, and the other is backup, launching script when changing state. Simple implementation, KISS. Production ready (at least it works for me :)

Life will be too easy !

jwpfox's user avatar

jwpfox

5,06411 gold badges45 silver badges42 bronze badges

answered Nov 12, 2016 at 7:06

Rajesh Pal's user avatar

1

This post describes how to keep a child process alive in a BASH script:

How do I write a bash script to restart a process if it dies?

This worked great for calling another BASH script.

However, I tried executing something similar where the child process is a Python script, daemon.py which creates a forked child process which runs in the background:

#!/bin/bash

PYTHON=/usr/bin/python2.6

function myprocess {


$PYTHON daemon.py start

}
NOW=$(date +"%b-%d-%y")

until myprocess; do
     echo "$NOW Prog crashed. Restarting..." >> error.txt
     sleep 1
done

Now the behaviour is completely different. It seems the python script is no longer a child of of the bash script but seems to have ‘taken over’ the BASH scripts PID — so there is no longer a BASH wrapper round the called script…why?

Community's user avatar

asked Apr 26, 2010 at 15:00

chris's user avatar

2

A daemon process double-forks, as the key point of daemonizing itself — so the PID that the parent-process has is of no value (it’s gone away very soon after the child process started).

Therefore, a daemon process should write its PID to a file in a «well-known location» where by convention the parent process knows where to read it from; with this (traditional) approach, the parent process, if it wants to act as a restarting watchdog, can simply read the daemon process’s PID from the well-known location and periodically check if the daemon is still alive, and restart it when needed.

It takes some care in execution, of course (a «stale» PID will stay in the «well known location» file for a while and the parent must take that into account), and there are possible variants (the daemon could emit a «heartbeat» so that the parent can detect not just dead daemons, but also ones that are «stuck forever», e.g. due to a deadlock, since they stop giving their «heartbeat» [[via UDP broadcast or the like]] — etc etc), but that’s the general idea.

answered Apr 26, 2010 at 15:20

Alex Martelli's user avatar

Alex MartelliAlex Martelli

837k165 gold badges1209 silver badges1388 bronze badges

You should look at the Python Enhancement Proposal 3143 (PEP) here. In it Ben suggests including a daemon library in the python standard lib. He goes over LOTS of very good information about daemons and is a pretty easy read. The reference implementation is here.

answered Apr 26, 2010 at 16:10

Paul Hildebrandt's user avatar

1

It seems that the behavior is completely different because here your «daemon.py» is launched in background as a daemon.

In the other link you pointed to the process that is surveyed is not a daemon, it does not start in the background. The launcher simply wait forever that the child process stop.

There is several ways to overcome this. The classical one is the way @Alex explain, using some pid file in conventional places.

Another way could be to build the watchdog inside your running daemon and daemonize the watchdog… this would simulate a correct process that do not break at random (something that shouldn’t occur)…

answered Apr 26, 2010 at 15:20

kriss's user avatar

krisskriss

23.1k17 gold badges97 silver badges115 bronze badges

Make use of ‘https://github.com/ut0mt8/simple-ha’ .

simple-ha

Tired of keepalived, corosync, pacemaker, heartbeat or whatever ? Here a simple daemon wich ensure a Heartbeat between two hosts. One is active, and the other is backup, launching script when changing state. Simple implementation, KISS. Production ready (at least it works for me :)

Life will be too easy !

jwpfox's user avatar

jwpfox

5,06411 gold badges45 silver badges42 bronze badges

answered Nov 12, 2016 at 7:06

Rajesh Pal's user avatar

1

I am running my Python script in the background in my Ubuntu machine (12.04) like this —

nohup python testing.py > test.out &

Now, it might be possible that at some stage my above Python script can die for whatever reason.

So I am thinking to have some sort of cron agent in bash shell script which can restart my above Python script automatically if it is killed for whatever reason.

Is this possible to do? If yes, then what’s the best way to solve these kind of problem?

UPDATE:

After creating the testing.conf file like this —

chdir /tekooz
exec python testing.py
respawn

I ran below sudo command to start it but I cannot see that process running behind using ps ax?

root@bx13:/bezook# sudo start testing
testing start/running, process 27794
root@bx13:/bezook# ps ax | grep testing.py
27806 pts/3    S+     0:00 grep --color=auto testing.py

Any idea why px ax is not showing me anything? And how do I check whether my program is running or not?

This is my python script —

#!/usr/bin/python
while True:
    print "Hello World"
    time.sleep(5)

asked Jan 5, 2014 at 7:33

arsenal's user avatar

arsenalarsenal

2,95317 gold badges43 silver badges49 bronze badges

On Ubuntu (until 14.04, 16.04 and later use systemd) can use upstart to do so, better than a cron job. You put a config setup in /etc/init and make sure you specify respawn

It could be a minimal file /etc/init/testing.conf (edit as root):

chdir /your/base/directory
exec python testing.py
respawn

And you can test with /your/base/directory/testing.py:

from __future__ import print_function

import time

with open('/var/tmp/testing.log', 'a') as fp:
    print(time.time(), 'done', file=fp)
    time.sleep(3)

and start with:

sudo start testing

and follow what happens (in another window) with:

tail -f /var/tmp/testing.log

and stop with:

sudo stop testing

You can also add [start on][2] to have the command start on boot of the system.

answered Jan 5, 2014 at 7:59

Zelda's user avatar

ZeldaZelda

5,9601 gold badge20 silver badges27 bronze badges

6

You could also take a more shell oriented approach. Have your cron look for your script and relaunch it if it dies.

  1. Create a new crontab by running crontab -e. This will bring up a window of your favorite text editor.

  2. Add this line to the file that just opened

    */5 * * * * pgrep -f testing.py || nohup python /home/you/scripts/testing.py > test.out
    
  3. Save the file and exit the editor.

You just created a new crontab which will be run every 5 minutes and launch your script unless it is already running. See here for a nice little tutorial on cron. The official Ubuntu docs on cron are here.

The actual command being run is pgrep which searches running processes for the string given in the command line. pgrep foo will search for a program named foo and return its process identifier. pgrep -f makes it search the entire command line used to launch the program and not only the program name (useful because this is a python script).

The || symbol means «do this if the previous command failed». So, if your script is not running, the pgrep will fail since it will find nothing and your script will be launched.

answered Jan 5, 2014 at 9:24

terdon's user avatar

terdonterdon

226k62 gold badges423 silver badges632 bronze badges

14

You shouldn’t really use this for production, but you could:

#!/bin/sh

while true; do
  nohup python testing.py >> test.out
done &

If, for any reason, python process exits, the shell loop will continue and restart it, appending to the .out file as desired. Nearly no overhead and takes very little time to set up.

answered Jan 5, 2014 at 12:17

K3---rnc's user avatar

K3—rncK3—rnc

3,0241 gold badge16 silver badges9 bronze badges

You can have the testing program redirect the output using a commandline option
and then use a simple python script to restart the program indefinitely:

import subprocess

while True:
    try:
        print subprocess.check_output(['python', 'testing.py'])
    except KeyboardInterrupt:
        break

you can put this program in the background, and once you want to stop just pull it into the foreground and kill it.

answered Jan 5, 2014 at 8:16

Anthon's user avatar

AnthonAnthon

76.9k42 gold badges159 silver badges217 bronze badges

There are a number of ways to monitor and respawn processes under UNIX/Linux. One of the oldest is a «respawn» entry in /etc/inittab … if you’re using the old SysV init system. Another method is to use the supervisor daemon from DJ Bernstein’s daemontools package. Other options are to use features in Ubuntu upstart … or systemd or others.

But you can look at alternatives init and in the Python code for Pardus: mudur daemon in particular.

If you decide to go with a cron job (and PID file handling) then consider reading this PEP 3143 and perhaps using its reference implementation.

As I alluded to in my other comments, robust PID file handling is tricky. It’s prone to races and corner cases. It gets trickier if there’s any chance that your PID file ends up on an NFS or other networked filesystem (some of the atomicity guarantees you get with the file handling semantics on proper local UNIX/Linux filesystems go away on some versions and implementations of NFS, for example). Also the semantics around file locking under UNIX can be tricky. (Does an flock or fcntl lock get released promptly, in your target OS, when the process holding it is killed with SIGKILL, for example?).

answered Jan 5, 2014 at 7:58

Jim Dennis's user avatar

Jim DennisJim Dennis

6002 silver badges11 bronze badges

You can also use monit Or Process monitoring with ps-watcher

Monit is an open source utility for managing and monitoring,
processes, programs, files, directories and filesystems on a UNIX
system. Monit conducts automatic maintenance and repair and can
execute meaningful causal actions in error situations.

Here is example for your scenario:

check process myprocessname
        matching "myprocessname"
        start program = "nohup /usr/bin/python /path/testing.py > /tmp/test.out &"
        stop program = "/usr/bin/killall myprocessname"

Take look at monit examples

answered Jan 5, 2014 at 9:43

Rahul Patil's user avatar

Rahul PatilRahul Patil

23.5k25 gold badges79 silver badges95 bronze badges

You need a supervisor, you can use supervisor. It is python based supervisor, therefore easy to modify if you need to.

Control is with files with .ini file syntax.

answered Jan 5, 2014 at 10:59

user41123's user avatar

user41123user41123

1942 silver badges6 bronze badges

Terdon’s answer, did not work for me, because
pgrep -f testing.py was never ‘failing’. It would grab the pid for the cron job (because of the -f option). However, without the -f option pgrep won’t find testing.py because there’s no process called testing.py.

My solution to this was to change

pgrep -f testing.py

to

pgrep -f testing.py | pgrep python

this means the full crontab job would be:

*/5 * * * * pgrep -f testing.py | pgrep python || nohup python /home/you/scripts/testing.py > test.out

Stephen Rauch's user avatar

answered Jun 15, 2017 at 20:00

Matt's user avatar

In my case, as a quick-fix, I wanted to keep my program running when it exited with en error or it was killed.
On the other hand, I wanted to stop the execution when the program terminated correctly (return code = 0)

I have tested it on Bash. It should work fine in any other shell

#!/bin/sh

echo ""
echo "Use: $0 ./instagram.py"
echo ""

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done)

answered Dec 27, 2018 at 12:53

user9869932's user avatar

For terdon’s answer, pgrep -f testing.py will never return false according to the comments in here:

I think the issue is that cron spawns a shell to run your command, and the arguments of that shell are matched by pgrep since you are using -f

For Matt’s answer, pgrep -f testing.py is useless since pgrep python matches any running Python script. So if two Python script cronjob, the second cronjob will never run.

And then I found the solution to solve pgrep -f testing.py in the comment here: https://askubuntu.com/questions/1014559/running-pgrep-in-a-crontab?noredirect=1&lq=1

My cron for running two Python scripts:

* * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript1.py' || nohup /usr/bin/python36 /home/ec2-user/myscript1.py

0 * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript2.py' || nohup /usr/bin/python36 /home/ec2-user/myscript2.py

Rui F Ribeiro's user avatar

Rui F Ribeiro

54.8k26 gold badges143 silver badges220 bronze badges

answered Mar 8, 2019 at 19:28

Frank's user avatar

FrankFrank

1012 bronze badges

In Ubuntu this works for me thanks to --wait

#!/bin/bash

while :
do
  sleep 5
  gnome-terminal --wait -- sh -c "python3 myscript.py 'myarg1'"
done

answered Nov 17, 2020 at 20:44

Chris's user avatar

ChrisChris

1011 bronze badge

There’s a Python module for that, forever.

The advantage being, hopefully, in using the same language for both the code and the watchdog. If it needs to be improved, one can find it in

cd $(python -c "import site; print(site.getusersitepackages())")

I’d install it with

python -mpip install --user --upgrade forever

and later use it with

python -mforever.run -t 9 -i 9 python script-to-watch.py

answered Feb 12, 2022 at 12:06

ArtemGr's user avatar

1

Here is a simple trick that I used to restart my python script after unhandled exception.

Let’s say I have this simple script called test.py that I want to run forever. It will just wait 2 seconds and throw an error.

import time time.sleep(2) raise Exception("Oh oh, this script just died")

Code language: JavaScript (javascript)

I use the following script called forever in the same directory:

#!/usr/bin/python from subprocess import Popen import sys filename = sys.argv[1] while True: print("nStarting " + filename) p = Popen("python " + filename, shell=True) p.wait()

Code language: JavaScript (javascript)

It uses python to open test.py as a new subprocess. It does so in an infinite while loop, and whenever test.py fails, the while loop restarts test.py as a new subprocess.

I’ll have to make the forever script executable by running chmod +x forever. Optionally forever script can be moved to some location in the PATH variable, to make it available from anywhere.

Next, I can start my program with:

./forever test.py

Which will result in the following output:

Starting test.py Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception("Oh oh, this script just died") Exception: Oh oh, this script just died Starting test.py Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception("Oh oh, this script just died") Exception: Oh oh, this script just died Starting test.py

Code language: JavaScript (javascript)

As you can tell, this script will run repeatedly, until it is killed with ctr+c.

Одной из важнейших задач при разработке серверных частей API или Ботов, обрабатывающих различные оповещения, является обеспечение их бесперебойной работы. Иными словами, необходимо автоматизированно произвести запуск всех необходимых скриптов при перезагрузке системы и перезапуск в случае ошибок и падений.

Одним из главных иструментов является supervisor.

Для установки достаточно набрать следующую команду в терминале (считаем что менеджер пакетов pip у вас уже уставнолен. Как это сделать читайте в статье Создаем бота для telegram).

sudo pip install supervisor

Супервизор позволяет следить за состоянием приложений, останавливать, запускать и перезапускать их. Для начала нам нужно создать конфигурационный файл для вашей программы, где мы опишем основные правила перезапуска и логирования. По умолчанию можно воспользоваться файлом:

/etc/supervisor/supervisord.conf

Удалим все содержимое и впишем следующий текст:

[program:github_server]
command=python server.py
directory=/var/www/codex.bot/
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/codex.bot/logs/app_sd.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false
loglevel=warn

В примере мы указываем, что хотим обеспечить контроль скрипта server.py, находящегося в директории /var/www/codex.bot и уточняем еще пару настроек логирования ошибок. Если супервизор у вас еще не запущен, выполните команду:

supervisord

Теперь можно попросить супервизор прочитать данные из конфига:

supervisorctl reread

Для просмотра статуса запущенных процессов воспользуйтесь командой:

supervisorctl status

Процесс под названием “github_server” (название указывается в конфиге) будет находится в состоянии “STOPPED”.

Запустим его:

supervisorctl start

Теперь в статусе будет отображено состояние “RUNNING”. Для остановки процесса можно пользоваться командой:

supervisorctl stop

Наконец, если принудительно завершить процесс:

sudo killall python

Он все равно будет перезапущен супервизором:

Состояние до завершения: github_server RUNNING pid 21755, uptime 0:03:57
Состояние после завершения: github_server RUNNING pid 21929, uptime 0:00:01

Видно, что сервер был перезапущен. Более подробно можно почитать в официальной документации.

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

1

Автоматически перезапускать скрипт

05.07.2021, 16:29. Показов 6588. Ответов 14


Как контролировать постоянно работающий скрипт, чтобы при вылетах его перезапускать? Как вариант, можно даже перезапускать скрипт просто по времени, например, каждые 3 часа

Добавлено через 14 секунд
Подойдет решение со сторонним софтом

0

Matrix3007

194 / 160 / 41

Регистрация: 13.05.2019

Сообщений: 828

05.07.2021, 16:37

2

Python
1
2
3
import os
 
os.system("Путь до запускатора")

1

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

05.07.2021, 17:18

 [ТС]

3

А os.system() автоматически перезапускает скрипт? Или ты советуешь в отдельном скрипте реализовать и запуск, и закрытие основного скрипта, с интервалом в нужное время?

0

194 / 160 / 41

Регистрация: 13.05.2019

Сообщений: 828

05.07.2021, 17:35

4

Joey, os.system() это вополнение команды в консоли. Если запускать нужно экзешник, то можно как-то на пид процесса ориентироваться, если нет, то хз.

0

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

05.07.2021, 17:54

 [ТС]

5

Видимо мы не поняли друг друга, мне нужно, чтобы после ошибки мой скрипт на питоне не стоял как вкопанный, а перезапускался

0

194 / 160 / 41

Регистрация: 13.05.2019

Сообщений: 828

05.07.2021, 17:57

6

Joey, А обработка исключений на что?

0

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

06.07.2021, 22:01

 [ТС]

7

С потоками не умею еще

0

Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

07.07.2021, 02:00

8

Цитата
Сообщение от Joey
Посмотреть сообщение

после ошибки мой скрипт на питоне не стоял как вкопанный,

Он у тебя должен упасть после ошибки (без обработки исключений). Каким образом он «стоит»? Так не бывает.
Чтобы он не падал, нужно обрабатывать все исключения и писать логику для всех ожидаемых ошибок.

1

3654 / 2234 / 490

Регистрация: 07.11.2019

Сообщений: 3,781

07.07.2021, 06:16

9

Цитата
Сообщение от Joey
Посмотреть сообщение

Подойдет решение со сторонним софтом

Можно из приложения сделать службу с автоматическим перезапуском после сбоя. См. https://nssm.cc/

1

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

07.07.2021, 09:31

 [ТС]

10

Цитата
Сообщение от Garry Galler
Посмотреть сообщение

Каким образом он «стоит»? Так не бывает.

Глупость сморозил, запускаю скрипт в Wing и оставляю, когда проверяю, иногда стоит ошибка о разрыве сети (скрипт работает с сокетами)

Цитата
Сообщение от Garry Galler
Посмотреть сообщение

Чтобы он не падал, нужно обрабатывать все исключения и писать логику для всех ожидаемых ошибок.

В питоне слаб, просто пришлось чужую прогу под себя доделывать

0

Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

07.07.2021, 13:00

11

Цитата
Сообщение от Joey
Посмотреть сообщение

скрипт работает с сокетами

Ну дак покажи кусок кода с запуском прослушивания сокетов.
Там можно поставить try except и ничего не будет падать.

0

IamHacker

-59 / 0 / 0

Регистрация: 11.06.2021

Сообщений: 49

07.07.2021, 19:05

12

Здравствуйте, рассмотрев все ответы могу впринципе доработать и сделать чуть чуть подругому:

Python
1
2
3
4
5
6
7
8
9
10
11
import os
import sys
 
def be_like():
    var = input("You be like XDD?").lower()
    if var == "yes":
        print("Ahah eto she primer boshe")
 
if __имя__ == '__main__':
   be_like()
    os.execv(__путь__, sys.argv)  iteration.

0

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

16.07.2021, 15:22

 [ТС]

13

Лучший ответ Сообщение было отмечено Рыжий Лис как решение

Решение

Решил задачу супервизором Supervisord, всем спасибо

0

Модератор

Эксперт Python

1351 / 648 / 207

Регистрация: 23.03.2014

Сообщений: 3,051

16.07.2021, 18:01

14

Joey, кодом поделитесь?
Вдруг, кому сгодится)

0

Joey

Джоуи

1073 / 635 / 240

Регистрация: 05.05.2015

Сообщений: 3,546

Записей в блоге: 2

21.07.2021, 10:48

 [ТС]

15

Это не код. Есть такая прога supervisord, устанавливается просто

Bash
1
sudo apt-get install supervisor

висит на порте :9001
он следит за процессами, заданными в настройках, если какой упал — перезапускает

1

IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

21.07.2021, 10:48

Помогаю со студенческими работами здесь

ГуглХром автоматически запускается и периодически открывает рекламные вкладки, AutoLogger не выполняет скрипт
Доброго времени суток. Изначально была единственная проблема связанная с автоматическим запуском…

Нужен скрипт, который c правами админа в профилях пользователей автоматически собирает их email-ы
Здравствуйте. Нужен специальный скрипт.
Работа скрипта должна проходить на форуме. Форум на движке…

Нужен ява-скрипт, который бы заставлял кнопку сабмит нажиматься автоматически через 3 сек.
Есть форма с кнопкой submit.

Нужен ява-скрипт, который бы заставлял кнопку сабмит нажиматься…

Как не перезапускать программу?
Написал калькулятор, запустил, после одного вычисления приходиться перезапускать калькулятор, для…

Приходится перезапускать проводник
Всем привет. В общем проблема такая. После запуска компа он перестает реагировать на команды мышки….

Создайте скрипт, который бы автоматически выводил дату создания файла определенного формата. Для jpeg файлов, независимо
Создайте скрипт, который бы автоматически выводил дату создания файла определенного формата. Для…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

15

Следующее не работает. У меня есть программа, которая подключается к веб-странице, но иногда из-за некоторых проблем она не может подключиться. Я хочу, чтобы программа полностью перезапустилась после самой ошибки. Представьте, что основная функция вызывает программу, как я могу написать такой код?

import numpy as np

def main():
    np.load('File.csv')

for i in range(1, 10):
    try:
        main()
    except Exception as e:
        print e
        print 'Restarting!'
        main()

3 ответа

Лучший ответ

Чтобы сделать это внутри Python, используйте try/except соответственно:

import numpy as np

def main():
    np.load('File.csv')

for i in range(1, 10):
    try:
        main()
    except Exception as e:
        print e
        print 'Restarting!'
        continue
    else:
        break

Для простых инструкций это работает, но если ваш код становится более сложным, помещение всей функции main() в блок try/except может скрыть исключения и затруднить отладку вашей программы. Таким образом, я бы порекомендовал обработать перезапуск вне питона, например в скрипте bash.


2

dron22
8 Апр 2016 в 13:53

Вы можете очень хорошо использовать рекурсивную функцию здесь для автоматического перезапуска кода. используйте setrecursionlimit (), чтобы определить количество попыток следующим образом:

import numpy as np
import sys
sys.setrecursionlimit(10)  # set recursion depth limit


def main():
    try:
        a = np.load('file.csv')
        if a:
            return a
    except Exception as e:
        return main()

result = main()
print result

Надеюсь это поможет :)


1

hemraj
8 Апр 2016 в 14:16

Для чего-то подобного (подключение к веб-странице) часто лучше устанавливать верхний предел на основе времени, а не количества попыток подключения. Так что используйте цикл while:

import numpy as np
import time

def main():
    np.load('file.csv')

start = time.time()
stop = start + 5
attempts = 0
result = 'failed'

while True:
    if time.time()<stop:
        try:
            main()
        except Exception as e:
            attempts += 1
            print e
            time.sleep(0.1) # optional
            print 'Restarting!'
            continue
        else:
            result = 'succeeded'
    print 'Connection %s after %i attempts.' % (result, attempts)
    break

Необязательно: я включил паузу в 100 мс после каждой неудачной попытки. Это может помочь с установлением соединения иногда.

Затем оберните все это в функцию, которую вы можете использовать в будущем для других проектов:

# retry.py

import time

def retry(f, seconds, pause = 0):
    start = time.time()
    stop = start + seconds
    attempts = 0
    result = 'failed'

    while True:
        if time.time()<stop:
            try:
                f()
            except Exception as e:
                attempts += 1
                print e
                time.sleep(pause)
                print 'Restarting!'
                continue
            else:
                result = 'succeeded'
        print '%s after %i attempts.' % (result, attempts)
        break

Теперь просто сделай это:

import numpy as np
from retry import retry

def main():
    np.load('file.csv')

retry(main, 5, 0.1)

Процедура тестирования:

class RetryTest():
    def __init__(self, succeed_on = 0, excp = Exception()):
        self.succeed_on = succeed_on
        self.attempts = 0
        self.excp = excp
    def __call__(self):
        self.attempts += 1
        if self.succeed_on == self.attempts:
            self.attempts = 0
        else:
            raise self.excp

retry_test1 = RetryTest(3)
retry(retry_test1, 5, 0.1)
# succeeded after 3 attempts.
retry_test2 = RetryTest()
retry(retry_test2, 5, 0.1)
# failed after 50 attempts.


1

Rick supports Monica
8 Апр 2016 в 23:32

How do you make a python program automatically restart itself? So let’s say there is a really simple program like:

var = input("Hi! I like cheese! Do you like cheese?").lower()
if var == "yes":
    print("That's awesome!")

Now, in a Python Shell, you would have to press either the Run button and then ‘Run Module (F5)’ or just the F5 key on your keyboard. That is the first time you run it. When the program ended, you would go back to your Cheese.py file and then press F5 to run the program again.

Everybody with me here?
OK, so my question is, how do you make the program restart itself automatically without you having to manually do it?

martineau's user avatar

martineau

117k25 gold badges161 silver badges290 bronze badges

asked Mar 15, 2016 at 17:42

DavidEclipse's user avatar

3

It depends on what you mean by «restart itself.» If you just want to continuously execute the same code, you can wrap it in a function, then call it from within a while True loop, such as:

>>> def like_cheese():
...     var = input("Hi! I like cheese! Do you like cheese?").lower()  # Corrected the call to `.lower`.
...     if var == "yes":
...         print("That's awesome!")
...
>>> while True:
...     like_cheese()
...
Hi! I like cheese! Do you like cheese?yes
That's awesome!
Hi! I like cheese! Do you like cheese?yes
That's awesome!

If you want to actually restart the script you can execute the script again, replacing the current process with the new one by doing the following:

#! /bin/env python3
import os
import sys

def like_cheese():
    var = input("Hi! I like cheese! Do you like cheese?").lower()
    if var == "yes":
        print("That's awesome!")

if __name__ == '__main__':
    like_cheese()
    os.execv(__file__, sys.argv)  # Run a new iteration of the current script, providing any command line args from the current iteration.

This will continuously re-run the script, providing the command line arguments from the current version to the new version. A more detailed discussion of this method can be found in the post «Restarting a Python Script Within Itself» by Petr Zemek.

One item that this article notes is:

If you use the solution above, please bear in mind that the exec*()
functions cause the current process to be replaced immediately,
without flushing opened file objects. Therefore, if you have any
opened files at the time of restarting the script, you should flush
them using f.flush() or os.fsync(fd) before calling an exec*()
function.

answered Mar 15, 2016 at 17:55

Deacon's user avatar

DeaconDeacon

3,51529 silver badges52 bronze badges

1

or you can try

$ chmod a+x "name".py

Then, you can run the script via

$ ./daemon.py

In such a situation, to restart the script, use the following code:

os.execv(__file__, sys.argv)

Otherwise, when you run the script via

$ python daemon.py

use this code:

os.execv(sys.executable, ['python'] + sys.argv)

Either way, do not forget to import the sys module

L_J's user avatar

L_J

2,29510 gold badges24 silver badges28 bronze badges

answered Jul 14, 2018 at 16:32

user10081708's user avatar

0

I use terminal on my Mac to re-start some of my python scripts with the function below.

import subprocess  
def run_again(cmd):
    subprocess.call(["bash", "-c", "source ~/.profile; " + cmd])  

Note: Don’t forget the space character after «profile;» or the function may fail silently!

Then at the bottom of my script to be re-started:

if some_condition:  
    run_again("python my_script.py %s" % my_new_arguments)  

For the original question about the cheese script:

if var != 'yes':  
    run_again("python my_cheese_script.py")  

answered Oct 13, 2017 at 18:13

exbctel's user avatar

exbctelexbctel

1951 silver badge9 bronze badges

You can just use a shell script like test.sh and make sure in your linux terminal you chmod +x test.sh

As for the code:

#!/bin/bash

while :
do
  sleep 5
  gnome-terminal --wait -- sh -c "python3 myscript.py 'myarg1'"
done

answered Nov 17, 2020 at 20:46

Chris's user avatar

ChrisChris

17.2k15 gold badges56 silver badges76 bronze badges

You can wrap something in while True: to make it execute repeatedly, as True will always evaluate to True, like this:

while True:
    var = input("Hi! I like cheese! Do you like cheese?").lower() # <-- You had missed parentheses here        
    if var == "yes":
        print("That's awesome!")

There’s another issue with your code though; you haven’t called lower by putting parentheses after it.

answered Mar 15, 2016 at 17:44

Aaron Christiansen's user avatar

7

Одной из важнейших задач при разработке серверных частей API или Ботов, обрабатывающих различные оповещения, является обеспечение их бесперебойной работы. Иными словами, необходимо автоматизированно произвести запуск всех необходимых скриптов при перезагрузке системы и перезапуск в случае ошибок и падений.

Одним из главных иструментов является supervisor.

Для установки достаточно набрать следующую команду в терминале (считаем что менеджер пакетов pip у вас уже уставнолен. Как это сделать читайте в статье Создаем бота для telegram).

sudo pip install supervisor

Супервизор позволяет следить за состоянием приложений, останавливать, запускать и перезапускать их. Для начала нам нужно создать конфигурационный файл для вашей программы, где мы опишем основные правила перезапуска и логирования. По умолчанию можно воспользоваться файлом:

/etc/supervisor/supervisord.conf

Удалим все содержимое и впишем следующий текст:

[program:github_server]
command=python server.py
directory=/var/www/codex.bot/
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/codex.bot/logs/app_sd.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false
loglevel=warn

В примере мы указываем, что хотим обеспечить контроль скрипта server.py, находящегося в директории /var/www/codex.bot и уточняем еще пару настроек логирования ошибок. Если супервизор у вас еще не запущен, выполните команду:

supervisord

Теперь можно попросить супервизор прочитать данные из конфига:

supervisorctl reread

Для просмотра статуса запущенных процессов воспользуйтесь командой:

supervisorctl status

Процесс под названием “github_server” (название указывается в конфиге) будет находится в состоянии “STOPPED”.

Запустим его:

supervisorctl start

Теперь в статусе будет отображено состояние “RUNNING”. Для остановки процесса можно пользоваться командой:

supervisorctl stop

Наконец, если принудительно завершить процесс:

sudo killall python

Он все равно будет перезапущен супервизором:

Состояние до завершения: github_server RUNNING pid 21755, uptime 0:03:57
Состояние после завершения: github_server RUNNING pid 21929, uptime 0:00:01

Видно, что сервер был перезапущен. Более подробно можно почитать в официальной документации.

  • Перенос слова считается орфографической ошибкой
  • Перезапуск бота при ошибке
  • Перенос на ios ошибка переноса
  • Перезагрузите чтобы устранить ошибки диска перезагрузка не помогает
  • Перенашивал идею лексическая ошибка