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
3,72723 gold badges33 silver badges46 bronze badges
asked Jul 8, 2013 at 18:02
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)
answered Jul 8, 2013 at 18:05
abarnertabarnert
355k52 gold badges601 silver badges673 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
djechlindjechlin
59.3k35 gold badges162 silver badges291 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!
answered Mar 1, 2020 at 4:50
0
In your exception make a recursive call
except:
queryRepeatedly()
answered Jul 8, 2013 at 18:06
sedavidwsedavidw
11.1k13 gold badges61 silver badges95 bronze badges
4
Как сделать так чтобы скрипт на питоне при ошибке заново запускался?
Вот у меня есть телеграм бот, и иногда он стопается, мол ошибка (там другая история).
И как сделать так, чтобы скрипт автоматически после остановки запускался заново (python bot.py)?
-
Вопрос задан
-
2429 просмотров
while true; do python bot.py; done
Можно с помощью инструкций try/except.
def function():
try:
a = input("Enter a number")
b = int(a) / 0
except:
function()
function()
Поместите туда свой код, при ошибке, функция будет вызвана заново.
Пригласить эксперта
-
Показать ещё
Загружается…
21 сент. 2023, в 22:23
5000 руб./за проект
21 сент. 2023, в 20:54
10000 руб./за проект
21 сент. 2023, в 20:40
20000 руб./за проект
Минуточку внимания
Одной из важнейших задач при разработке серверных частей 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
Видно, что сервер был перезапущен. Более подробно можно почитать в официальной документации.
In Python, sometimes it is required to restart a script automatically when it encounters an error or when it is unable to complete a task. The script should be able to automatically restart itself without any manual intervention. There are different methods to achieve this, including using the «try-except» block, using the «os» module, or using the «subprocess» module. Each method has its own advantages and limitations, and it is important to choose the one that best suits the requirements of the specific script. In this article, we will discuss the following methods to automatically restart a Python script:
Method 1: Try-Except Block
To make a Python script automatically restart itself using a try-except
block, you can use a while
loop that continuously runs the script until it is successful. Here is an example code:
import time
while True:
try:
# Your script code goes here
print("Hello World!")
# End of your script code
except Exception as e:
# If an exception occurs, print the error message and wait for a few seconds
print(f"Error: {e}")
time.sleep(5)
else:
# If the script runs successfully, print a success message and break the loop
print("Script ran successfully!")
break
In this example, the while
loop continuously runs the script until it is successful. The try
block contains the actual script code that you want to run. If an exception occurs, the except
block prints the error message and waits for a few seconds before trying again. The else
block executes if the script runs successfully, prints a success message, and breaks the loop.
You can customize the code to fit your specific needs. For example, you can increase or decrease the waiting time after an exception, or add more exception types to catch. The key concept is to use a try-except
block inside a while
loop to continuously run the script until it is successful.
Method 2: OS Module
Here is a step-by-step guide on how to automatically restart a Python script using the OS module:
Step 1: Import the OS module
The first step is to import the OS module in your Python script. This can be done using the following code:
Step 2: Define the function to restart the script
Next, you need to define a function that will restart the script. This can be done using the following code:
def restart_program():
python = sys.executable
os.execl(python, python, * sys.argv)
This function uses the os.execl()
method to execute the Python interpreter again with the same arguments as the current script.
Step 3: Add the restart code in your script
Now, you need to add the code to restart the script at the end of your script. This can be done using the following code:
if __name__ == "__main__":
# Your script code here
# Restart the script
restart_program()
This code checks if the script is being executed as the main program, and if so, executes the script code and then restarts the script using the restart_program()
function.
Full code example
Here is the full code example on how to automatically restart a Python script using the OS module:
import os
import sys
def restart_program():
python = sys.executable
os.execl(python, python, * sys.argv)
if __name__ == "__main__":
# Your script code here
# Restart the script
restart_program()
This code will execute your script code and then automatically restart the script.
Method 3: Subprocess Module
Restarting a Python Script Automatically with Subprocess Module
Here’s an example code snippet that demonstrates how to use the subprocess
module to restart a Python script automatically:
import subprocess
import sys
def restart_program():
"""Restarts the current program, with file objects and descriptors
cleanup
"""
try:
p = subprocess.Popen([sys.executable] + sys.argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except:
raise SystemExit("Failed to restart program")
else:
output, error = p.communicate()
print(output.decode())
print(error.decode())
if __name__ == "__main__":
print("Starting program...")
while True:
try:
# Your code here
print("Program running...")
# End of your code
except Exception as e:
print(f"Error: {e}")
restart_program()
Here, the restart_program()
function restarts the current program by calling subprocess.Popen()
with the current executable and command-line arguments. The stdout
and stderr
arguments are set to subprocess.PIPE
to capture the output and error messages of the restarted program.
In the if __name__ == "__main__":
block, the code runs in an infinite loop, executing your code and catching any exceptions. If an exception occurs, the restart_program()
function is called to restart the program.
Note that this code is just an example, and you should modify it to suit your needs. Also, the subprocess
module may not work on all platforms, so you should test it thoroughly before using it in production.