Python Updater

Python mag durch seine üppige Modul-Bibliothek bestens für eine Vielzahl an Aufgaben gewappnet sein. Für so manches Konzept steht jedoch nicht immer ein allumfassender Helfer zur Verfügung, sodass hier und da ein wenig Eigeninitiative gefragt ist. So auch für die Funktion, eine bestehende Python-Datei durch eine weiteren zu aktualisieren.
Wie ein solches Update aussehen kann, wird im folgenden Beitrag beleuchtet.

Einleitung

Zunächst einmal möchte ich die Rahmenbedingungen erläutern. In meinem Setup verwende ich Python in der Version 3.12 sowie 3 Python Dateien:
– Eine erste Python-Datei die aktualisiert werden soll (old.py)
– Eine zweite Python-Datei die als Update dient und die erste überschreiben soll (new.py)
– Eine dritte Python-Datei die das Update-Programm darstellt (updater.py)
Das Update muss über eine separate Datei ausgeführt werden, da der Zugriff auf die zu aktualisierende Datei während des Updates ansonsten verweigert werden könnte. Der nachfolgende Code ist so strukturiert, dass sich die alte Python-Datei und der Updater im selben Ordner befinden. Die zu aktualisierende Datei kann an einem beliebigen Ort liegen.

Die alte zu aktualisierende Datei

Die erste zu aktualisierende Datei ist absichtlich kurz und knapp gehalten und soll nur der vereinfachten Demonstration dienen.
Der Updater besteht aus zwei Funktionen (check_for_updates und execute_updater). Innerhalb dieser Funktionen wird zunächst über den boolschen Wert der Variable update_available überprüft, ob ein Update vorliegt (Zeile 7). Falls dies zutrifft, startet die Funktion execute_updater. In ihr wird der aktuelle Arbeitspfad in eine Variable geschrieben und mit updater.py ergänzt (Zeile 18), sodass wir den kompletten Pfad zum updater.py erhalten. Soll der Updater von einem anderen Pfad aus aufgerufen werden, muss hier natürlich die Variable updater_path entsprechend angepasst werden. Ebenso ist es wichtig, den Pfad zur old.py in eine Variable zu speichern (Zeile 15) und hinterher bei der Ausführung des Updaters zur weiteren Verarbeitung mitzugeben (Zeile 21). Anschließend wird der Updater samt mitzugebender Variable gestartet.

Abschließend wird noch das aktive Programm (in unserem Fall ja die old.py) geschlossen, damit sichergestellt ist, dass das Update ordnungsgemäß durchgeführt werden kann (Zeile 24).
Der Block if name == „main“: (Zeile 26-27) ist eine Standardstruktur in Python und sorgt dafür, das die darin enthaltenen Teile des Codes nur dann ausgeführt werden, wenn das Skript direkt ausgeführt und nicht als importierte Funktion über ein anderes Skript ausgeführt wird.

import os
import sys
import subprocess

def check_for_updates():
    ### Check if an update is available
    update_available = True

    if update_available:
        ### Start the updater
        run_updater()

def run_updater():
    ### Get Path of old.py
    current_prgram_path = sys.argv[0]
    
    ### Path to the updater
    updater_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "updater.py")

    ### Start the Updater
    subprocess.run(["python", updater_path, str(current_prgram_path)])

    ### Close the current program
    sys.exit()

if __name__ == "__main__":
    check_for_updates()

Die neue Update-Datei

Die neue Update-Datei (new.py) trägt keine besondere Relevanz zur weiteren Durchführung des Updates bei und kann nach belieben gestaltet werden. Soll die Update-Möglichkeit bestehen bleiben, sollten natürlich sowohl die beiden zuvor erstellen Update-Funktionen (check_for_updates und run_updater), als auch die dazugehörige Code-Struktur erhalten bleiben, um diese aufzurufen.

Der Updater

Der Updater besteht lediglich aus einer einzigen Funktion, nämlich der update_program. Innerhalb dieser Funktion wird zunächst die Variable aus dem vorherigen Skript-Aufruf entgegengenommen (Zeile 7) und der Pfad zur neuen Python-Datei (new.py), die als Update-Datei fungiert, festgelegt (Zeile 10). Anschließend wird mit Hilfe des shutils.copy Befehls die neue Datei überschrieben (Zeile 13). Zum Schluß wird noch der Updater geschlossen (Zeile 16). Auch in diese Funktion wird mit Hilfe des Blocks if name == „main“: (aus den oben genannten Gründen) aufgerufen.

import os
import shutil
import sys

def update_program():
    ### Get variable from old.py
    current_prgram_path = sys.argv[1]

    ### Path to the new file
    new_version_path = "/home/marian/PycharmProjects/Python_Updater/new.py"

    ### Overwrite the new file over the old one
    shutil.copy(new_version_path, current_prgram_path)

    ### Close the updater
    sys.exit()

if __name__ == "__main__":
    update_program()

Somit hätten wir eine Möglichkeit geschaffen, bei Bedarf alte Python Dateien zu überschreiben.
Selbstverständlich ist dieses Konzept mit Fehleranalyse, grafischer Oberfläche und anderen Dateitypen beliebig erweiterbar und auch sind die zu behandelnden Dateien nicht auf Python beschränkt. Beachtet jedoch, dass je nach eingesetzter Datei-Infrastruktur der Aufruf und die Behandlung innerhalb der Python Umgebung variieren kann.

Bildquellen:
Update-Bild von Gerd Altmann auf Pixabay

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Nach oben scrollen