web-dev-qa-db-ja.com

自己更新を再開するpythonスクリプト

Webサイトから最新バージョンをダウンロードして実行中のスクリプトを上書きすることにより、最新の状態に保つスクリプトを作成しました。

スクリプトが更新された後にスクリプトを再起動するための最良の方法はわかりません。

何か案は?

個別の更新スクリプトは必要ありません。ああ、それは両方のlinux/windowsでも動作する必要があります。

41
Ashy

Linux、またはその他のUNIXの形式では、 os.execl や友人がこれに適しています-同じことで sys.executable を再実行する必要があるだけです前回実行されたパラメータ(sys.argv、多かれ少なかれ)またはそれが実際に再起動であることを次のインカネーションに通知する必要がある場合は、そのバリアント。 Windowsでは、 os.spawnl (および友人)があなたにできる最高のことです(ただし、移行中にos.execlや友人よりも一時的に多くの時間とメモリが必要になります)。

30
Alex Martelli

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)

私はこのテクニックを自分のコードで使用しましたが、うまく機能します。 (上記のウィンドウで引数の引用手順を実行する必要はありませんでしたが、引数にスペースやその他の特殊文字を含めることができる場合はおそらく必要です。)

18
Josh

私はこのようなものである最善の解決策だと思います:

通常のプログラム:

...

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

これがお役に立てば幸いです。

5
Joschua

最もクリーンなソリューションは、独立した更新スクリプトです!

その中でプログラムを実行し、新しいバージョンが利用可能であることを(終了時に)報告します。これにより、プログラムですべてのデータを保存し、アップデーターで更新を適用し、新しいバージョンを実行して、保存したデータをロードして続行できます。ユーザーにとっては、実際のプログラムを実行するアップデータシェルを実行するだけなので、これは完全に透過的です。

2
Roger Pate

Poconoチームは、開発サーバー用の非常に優れたリローダーをwerkzeug内部に持っています。コードを確認してください here (ファイルの下部にあります)。

1
Bryan McLemore

さらに、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()
1
sevenforce

reload(module) を使用してモジュールをリロードできます。

0
Alexandru

メインファイル:

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)更新機能を更新する必要がない場合、「メイン」は引き続き実行されます

0
takrliu