重新启动自我更新的Python脚本

发布于 2024-08-11 16:56:00 字数 151 浏览 7 评论 0 原文

我编写了一个脚本,该脚本可以通过从网站下载最新版本并覆盖正在运行的脚本来保持自身最新。

我不确定更新脚本后重新启动脚本的最佳方法是什么。

有什么想法吗?

我真的不想有一个单独的更新脚本。 哦,它也必须在 Linux/Windows 上运行。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

与君绝 2024-08-18 16:56:00

在 Linux 或任何其他形式的 unix 中, os.execl 和朋友们是一个不错的选择——你只需要重新执行 sys.executable ,其参数与上次执行时相同(sys.argv,或多或少)或其任何变体(如果您需要通知)你的下一个化身实际上是重新启动。在 Windows 上, os.spawnl (以及朋友) 是你能做的最好的事情(尽管在过渡期间它会比 os.execl 和朋友们暂时花费更多的时间和内存)。

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

℡寂寞咖啡 2024-08-18 16:56:00

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)

我已经在我自己的代码中使用了这种技术,效果很好。 (我没有费心在上面的窗口上执行参数引用步骤,但如果参数可能包含空格或其他特殊字符,则可能有必要。)

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

孤凫 2024-08-18 16:56:00

我认为最好的解决方案应该是这样的:

您的正常程序:

...

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

我希望这会对您有所帮助。

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.

胡大本事 2024-08-18 16:56:00

最干净的解决方案是单独的更新脚本!

在其中运行您的程序,报告(退出时)有新版本可用。这允许您的程序保存其所有数据,更新程序应用更新并运行新版本,然后加载保存的数据并继续。对于用户来说,这可以是完全透明的,因为他们只运行运行真实程序的 updater-shell。

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.

泅人 2024-08-18 16:56:00

主文件:

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”的新实例,

然后调用原始实例“主要”退出。

2)如果更新函数不需要更新,则“main”继续运行

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

旧时光的容颜 2024-08-18 16:56:00

为了额外支持使用 Python 的“-m”参数进行脚本调用,可以使用以下命令(基于 Alex 的答案;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()

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()
_失温 2024-08-18 16:56:00

做这样的事情不是更容易吗
非常简单,不需要额外的导入,并且与任何操作系统兼容,具体取决于您在 os.system 字段中输入的内容

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

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')
梦毁影碎の 2024-08-18 16:56:00

您可以使用 reload(module) 重新加载模块。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文