28

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
  • 119,623
  • 25
  • 170
  • 301
DavidEclipse
  • 417
  • 1
  • 4
  • 6
  • 4
    Do you mean you simply want to loop the program, or reload it, or... what? What's the actual problem you're trying to solve. – jonrsharpe Mar 15 '16 at 17:45
  • 1
    To put @jonrsharpe's comment in code: What about `while True: main()` ? Assuming `main()` is the function you're calling. – morxa Mar 15 '16 at 17:48
  • https://stackoverflow.com/a/33334183/1340631 has a nice solution. – scai Jan 06 '21 at 10:40

6 Answers6

42

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.

Deacon
  • 3,615
  • 2
  • 31
  • 52
  • @shaikmoeed - Don't know for certain, not a use case I'm certain I'd want to execute. Probably insert a hash function in a loop to restart if the source file had changed. I would be more likely to execute that use case if I were watching for changes in a config file. – Deacon Sep 26 '19 at 12:44
4

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
  • 2,351
  • 10
  • 23
  • 28
3

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")  
exbctel
  • 195
  • 1
  • 9
3

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
Chris
  • 18,075
  • 15
  • 59
  • 77
1

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.

Aaron Christiansen
  • 11,584
  • 5
  • 52
  • 78
0

I have written a blog post about this problem and I have provided its solution here in this blog post. Also I have created a repository for this.

My solution works with crontab python package, I create a cronjob to run the program (let's say 1 minute later) after exiting the program.