Seite 1 von 1

os.system

Verfasst: Dienstag 2. Februar 2021, 18:43
von Domroon
Hallo Leute,
ich brauchte eine einfache Möglichkeit eine Datei von einem Ort an den anderen zu kopieren. Folgendes Programm funktioniert gut.
Die Datei wird kopiert sobald Outlook geschlossen wird.
Um das Programm besser zu machen, möchte ich gerne vor dem Kopieren Abfragen ob die Datei im Ziel älter als die in der Quelle. Somit will ich vermeiden, dass Daten zerstört werden.
Bevor ich mit diesem Programm weiter mache, wollte ich fragen ob es eine schönere Möglichkeit gibt als stupide cmd-Befehle mithilfe von os.system einzubinden? Es muss doch etwas geben, was mehr der "pythonic-way" ist. Wenn ihr versteht was ich meine :lol:

Code: Alles auswählen

import os
while 1:
	if os.system('TaskList|Find "OUTLOOK.EXE" >NUL'):
		print("Programm läuft nicht")
	else:
		print("Programm läuft")
		while not os.system('TaskList|Find "OUTLOOK.EXE" >NUL'):
			print("Warte auf Beendigung")
		os.system('cp C:/Users\haeus/workspace/Testordner1/Datei.txt C:/Users/haeus/workspace/Testordner2/Datei.txt')
		print("Datei wurde kopiert")
Danke euch schonmal :wink:

Re: os.system

Verfasst: Dienstag 2. Februar 2021, 20:34
von __blackjack__
@Domroon: Wenn Du nicht in Python programmieren möchtest, dann lass es doch einfach. `os.system()` sollte man an sich schon nicht verwenden. Für das ausführen von externen Prozessen gibt es das `subprocess`-Modul.

Man muss auch nicht für Sachen die auch in Python gehen, eine externe Shell + externe Programme starten.

Zum Beispiel braucht man kein externes ``find`` um eine Zeichenkette in einer anderen zu suchen, so etwas kann Python selbst.

Und auch Dateien kopieren: da gibt es was im `shutil`-Modul.

Python hat einen eigenen Datentyp für Wahrheitswerte, da sollte man nicht 0 und 1 für missbrauchen.

Beide ``while``-Schleifen beschäftigen den Prozessor zu 100% mit Warten auf eine Bedingung. Das sollte man mindestens mit einem kleinen `time.sleep()` ausbremsen.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import shutil
import subprocess
from pathlib import Path
from time import sleep

BASE_PATH = Path("C:/Users/haeus/workspace")
SOURCE_FILE_PATH = BASE_PATH / "Testordner1" / "Datei.txt"
TARGET_PATH = BASE_PATH / "Testordner2"

PROGRAM_NAME = "OUTLOOK.EXE"


def is_running(search_term):
    result = subprocess.run(
        ["tasklist"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        check=True,
    )
    return search_term in result.stdout


def main():
    while True:
        if is_running(PROGRAM_NAME):
            print("Programm läuft")

            while is_running(PROGRAM_NAME):
                print("Warte auf Beendigung")
                sleep(0.1)

            shutil.copy(SOURCE_FILE_PATH, TARGET_PATH)
            print("Datei wurde kopiert")
        else:
            print("Programm läuft nicht")

        sleep(0.1)


if __name__ == "__main__":
    main()
Den Aufruf von ``tasklist`` würde ich loswerden wollen und das mit dem externen `psutils` lösen. Zumindest beim warten auf das Ende der/des Prozesse(s) kann man sich dann auch das „busy waiting“ sparen und blockierend auf das Ende der gefundenen Prozesse warten.

Re: os.system

Verfasst: Donnerstag 4. Februar 2021, 06:25
von Domroon
@__blackjack__: Vielen Dank für Deine schnelle Hilfe :wink:

Ich habe Versucht alle Deine Verbesserungen umzusetzen. Was hälst Du vom nachfolgenden Programm?

Code: Alles auswählen

#!/usr/bin/env python3
import shutil
import subprocess
from pathlib import Path
from time import sleep
import os
import time
import psutil

BASE_PATH = Path("C:/Users/haeus/workspace")
SOURCE_FILE_PATH = BASE_PATH / "Testordner1" / "Datei.txt"
TARGET_FILE_PATH = BASE_PATH / "Testordner2" / "Datei.txt"

PROGRAM_NAME = "OUTLOOK.EXE"

def source_is_newer(SOURCE_FILE_PATH, TARGET_FILE_PATH):
    statinfo_source = os.stat(SOURCE_FILE_PATH)
    statinfo_target = os.stat(TARGET_FILE_PATH)
    seconds_since_source_modification = int(time.time()) -int(statinfo_source.st_mtime)
    seconds_since_target_modification = int(time.time()) -int(statinfo_target.st_mtime)

    if seconds_since_target_modification >= seconds_since_source_modification:
        return True
    else:
        return False

def is_running(search_term):
    for proc in psutil.process_iter(['pid', 'name']):
        process_name = proc.info["name"]

        if process_name == search_term:
            return True

def main():
    while True:
        if is_running(PROGRAM_NAME):
            print("Programm läuft")

            while is_running(PROGRAM_NAME):
                print("Warte auf Beendigung")
                sleep(0.1)


            if source_is_newer(SOURCE_FILE_PATH, TARGET_FILE_PATH):
                print('Quelldatei ist neuer')
                shutil.copy(SOURCE_FILE_PATH, TARGET_FILE_PATH)
                print("Datei wurde kopiert")
            else:
                print('Quelldatei ist älter oder auf dem gleichen Stand')
                print('Datei wurde nicht kopiert')
            
        else:
            print("Programm läuft nicht")

        sleep(0.1)   

if __name__ == "__main__":
    main()
Ich wollte mir auch das "busy waiting" sparen wie Du sagtest. Also blockierend auf Beendigung des Prozesses warten. Allerdings verstehe ich nicht wie ich das umsetzen soll. Da ich selbst mit psutils ständig abfragen muss welche Prozesse gerade laufen.
Ich würde aber gerne Deine Idee mit dem "blockieren" sehr gerne umsetzen wollen.

Schöne Grüße

Re: os.system

Verfasst: Donnerstag 4. Februar 2021, 06:37
von sparrow
Ein schneller Blick in die Dokumentation zeigt, dass psutil extra eine Funktion hat, um auf das beenden von Prozessen zu warten.

Re: os.system

Verfasst: Donnerstag 4. Februar 2021, 06:40
von Domroon
@sparrow: Jap, genau in diesem Moment habe ich diese auch gefunden :ugeek:
Tut mir leid für meine doofheit :D
Werde dann mal versuchen das Programm dementsprechend zu verbessern.
Danke euch :wink:

Re: os.system

Verfasst: Donnerstag 4. Februar 2021, 07:02
von Sirius3
Die Parameter einer Funktion sind nie Konstanten, dürfen also nicht so geschrieben werden. Path-Objekte ganzen eine stat-Mothode. Wenn Du wissen willst, welche Datei neuer ist, warum vergleichst Du dann die Sekunden die zu zwei verschiedenen Zeitpunkten vergangen sind und nicht die Änderungsdaten direkt? Warum wandelst Du time.time() und st_mtime in int um?
Das if mit den returns True oder False ist unnötig kompliziert, weil der Vergleich ja schon True oder False ergibt.

Code: Alles auswählen

def source_is_newer(source_file_path, target_file_path):
    statinfo_source = source_file_path.stat()
    statinfo_target = target_file_path.stat()
    return statinfo_source.st_mtime <= statinfo_target.st_mtime