Restart python-script from within itself

I have a python-based GTK application that loads several modules. It is run from the (linux) terminal like so:

./myscript.py --some-flag setting

From within the program the user can download (using Git) newer versions. If such exists/are downloaded, a button appear that I wish would restart the program with newly compiled contents (including dependencies/imports). Preferably it would also restart it using the contents of sys.argv to keep all the flags as they were.

So what I fail to find/need is a nice restart procedure that kills the current instance of the program and starts a new using the same arguments.

Preferably the solution should work for Windows and Mac as well but it is not essential.


Solution 1:

You're looking for os.exec*() family of commands.

To restart your current program with exact the same command line arguments as it was originally run, you could use the following:

os.execv(sys.argv[0], sys.argv)

Solution 2:

I think this is a more elaborate answer, as sometimes you may end up with too many open file objects and descriptors, that can cause memory issues or concurrent connections to a network device.

import os
import sys
import psutil
import logging

def restart_program():
    """Restarts the current program, with file objects and descriptors
       cleanup
    """

    try:
        p = psutil.Process(os.getpid())
        for handler in p.get_open_files() + p.connections():
            os.close(handler.fd)
    except Exception, e:
        logging.error(e)

    python = sys.executable
    os.execl(python, python, *sys.argv)

Solution 3:

UPDATE - of the above answer with some example for future reference

I have runme.sh

#!/bin/bash
kill -9 server.py
python /home/sun/workspace/c/src/server.py &

And i have server.py where i need to restart the application itself, so i had:

os.system('runme.sh')

but that did not restart the application itself by following runme.sh, so when i used this way:

os.execl('runme.sh', '')

Then i was able to restart itself

Solution 4:

I know this solution isn't technically what you are asking for but if you want to be 100% sure you freed everything or don't want to rely on dependencies you could just run the script in from a loop in another:

import os, time

while 1:
    os.system("python main.py")
    print "Restarting..."
    time.sleep(0.2) # 200ms to CTR+C twice

Then you can restart main.py as simply as:

quit()

Solution 5:

For me this part worked like a charm:

def restart():
    import sys
    print("argv was",sys.argv)
    print("sys.executable was", sys.executable)
    print("restart now")

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

I got it here.