51

I have written a script that will keep itself up to date by downloading the latest version from a website and overwriting the running script.

I am not sure what the best way to restart the script after it has been updated.

Any ideas?

I don't really want to have a separate update script. oh and it has to work on both linux/windows too.

3
  • 2
    Hello! If your code is open source or personal, could I see it? I am trying to do something very similar to what you are doing and am having some trouble. I will provide attribution of course :) Commented Jul 30, 2019 at 20:20
  • 2
    @ChristopherConnery The really old code is here: github.com/drashy/leechr hope this helps you! Commented Jul 31, 2019 at 21:09
  • 2
    Wow! Really cannot thank you enough! Free Software FTW!! Commented Aug 1, 2019 at 2:22

8 Answers 8

35

In Linux, or any other form of unix, os.execl and friends are a good choice for this -- you just need to re-exec sys.executable with the same parameters it was executed with last time (sys.argv, more or less) or any variant thereof if you need to inform your next incarnation that it's actually a restart. On Windows, os.spawnl (and friends) is about the best you can do (though it will transiently take more time and memory than os.execl and friends would during the transition).

Sign up to request clarification or add additional context in comments.

3 Comments

Probably the best way to go if the script is simple enough.
One-liner for future reference: os.execl(sys.executable, *([sys.executable]+sys.argv))
@Josh Not in general. You will get prompt glitch on Windows if you using os.execl with e.g. input().
21

The CherryPy project has code that restarts itself. Here's how they do it:

    args = sys.argv[:]
    self.log('Re-spawning %s' % ' '.join(args))

    args.insert(0, sys.executable)
    if sys.platform == 'win32':
        args = ['"%s"' % arg for arg in args]

    os.chdir(_startup_cwd)
    os.execv(sys.executable, args)

I've used this technique in my own code, and it works great. (I didn't bother to do the argument-quoting step on windows above, but it's probably necessary if arguments could contain spaces or other special characters.)

1 Comment

They moved to github, here is a permalink which might be close to the 2011 version you posted.
5

I think the best solution whould be something like this:

Your normal program:

...

# ... part that downloaded newest files and put it into the "newest" folder

from subprocess import Popen

Popen("/home/code/reloader.py", shell=True) # start reloader

exit("exit for updating all files")

The update script: (e.g.: home/code/reloader.py)

from shutil import copy2, rmtree
from sys import exit

# maybie you could do this automatic:
copy2("/home/code/newest/file1.py", "/home/code/") # copy file
copy2("/home/code/newest/file2.py", "/home/code/")
copy2("/home/code/newest/file3.py", "/home/code/")
...

rmtree('/home/code/newest') # will delete the folder itself

Popen("/home/code/program.py", shell=True) # go back to your program

exit("exit to restart the true program")

I hope this will help you.

Comments

2

The cleanest solution is a separate update script!

Run your program inside it, report back (when exiting) that a new version is available. This allows your program to save all of its data, the updater to apply the update, and run the new version, which then loads the saved data and continues. To the user this can be completely transparent, as they just run the updater-shell which runs the real program.

1 Comment

You can, use your main program to check for updates. When a new update is available. download a new 'update.py'.... then execute it. 'update.py' will then close the old instance and spawn a new one.
1

Main File:

if __name__ == '__main__':

if os.path.isfile('__config.py'):
    print 'Development'
    push.update_server()
else:
    e = update.check()
    if not e: sys.exit()

Update File:

def check():
    e = 1.....perform checks, if something needs updating, e=0;
    if not e:
        os.system("python main.pyw")
    return e

Here's the logic:

Main program calls the update function

1) If the update function needs to update, than it updates and calls a new instances of "main"

Then the original instance of "main" exits.

2) If the update function does not need to update, then "main" continues to run

Comments

1

To additionally support script calls with Python's "-m" parameter the following can be used (based on the Alex's answer; Windows version):

os.spawnl(os.P_WAIT, sys.executable, *([sys.executable] +
    (sys.argv if __package__ is None else ["-m", __loader__.name] + sys.argv[1:])))
sys.exit()

Comments

0

Wouldn't it just be easier to do something like Very simple, no extra imports needed, and compatible with any OS depending on what you put in the os.system field

def restart_program():
  print("Restarting Now...")
  os.system('your program here')

Comments

-1

You can use reload(module) to reload a module.

1 Comment

I feel like this doesnt answer the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.