Перезапуск самообновляющегося скрипта Python - PullRequest
33 голосов
/ 17 ноября 2009

Я написал скрипт, который будет обновляться, загружая последнюю версию с веб-сайта и перезаписывая работающий скрипт.

Я не уверен, как лучше всего перезапустить скрипт после его обновления.

Есть идеи?

Я действительно не хочу иметь отдельный скрипт обновления. о, и это должно работать на обоих linux / windows тоже.

Ответы [ 8 ]

27 голосов
/ 17 ноября 2009

В Linux или любой другой форме Unix os.execl и друзья являются хорошим выбором для этого - вам просто нужно повторно выполнить sys.executable с те же параметры, с которыми он был выполнен в прошлый раз (sys.argv, более или менее) или любой их вариант, если вам нужно сообщить вашему следующему воплощению, что это на самом деле перезапуск. В Windows os.spawnl (и друзья) - это лучшее, что вы можете сделать (хотя на время это займет больше времени и памяти, чем os.execl и друзья во время перехода).

16 голосов
/ 22 апреля 2011

В проекте CherryPy есть код, который перезапускается сам. Вот как они это делают :

    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)

Я использовал эту технику в своем собственном коде, и она прекрасно работает. (Я не удосужился выполнить шаг цитирования аргументов в окнах выше, но, вероятно, это необходимо, если аргументы могут содержать пробелы или другие специальные символы.)

3 голосов
/ 18 ноября 2009

Я думаю, что лучшее решение будет примерно таким:

Ваша обычная программа:

...

# ... 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")

Сценарий обновления: (например, 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")

Надеюсь, это поможет вам.

2 голосов
/ 17 ноября 2009

Самое чистое решение - это отдельный скрипт обновления!

Запустите вашу программу внутри нее, сообщите (при выходе), что доступна новая версия. Это позволяет вашей программе сохранить все свои данные, средство обновления применяет обновление и запускает новую версию, которая затем загружает сохраненные данные и продолжает работу. Для пользователей это может быть совершенно прозрачно, поскольку они просто запускают оболочку обновления, которая запускает настоящую программу.

1 голос
/ 17 ноября 2009

Команда pocoo имеет очень хороший перегрузчик для своего сервера разработки внутри werkzueg. Проверьте код здесь (это ближе к концу файла).

0 голосов
/ 19 ноября 2014

Для дополнительной поддержки вызовов сценариев с параметром Python "-m" может использоваться следующее (в зависимости от ответа Алекса; версия для Windows):

os.spawnl(os.P_WAIT, sys.executable, *([sys.executable] +
    (sys.argv if __package__ is None else ["-m", __loader__.name] + sys.argv[1:])))
sys.exit()
0 голосов
/ 17 июля 2013

Основной файл:

if __name__ == '__main__':

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

Файл обновления:

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

Вот логика:

Основная программа вызывает функцию обновления

1) Если функция обновления нуждается в обновлении, то она обновляет и вызывает новые экземпляры "main"

Тогда исходный экземпляр "main" выходит.

2) Если функция обновления не нуждается в обновлении, то «main» продолжает работать

0 голосов
/ 17 ноября 2009

Вы можете использовать reload (module) для перезагрузки модуля.

...