os.system

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Domroon
User
Beiträge: 104
Registriert: Dienstag 3. November 2020, 10:27
Wohnort: Dortmund

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:
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
Domroon
User
Beiträge: 104
Registriert: Dienstag 3. November 2020, 10:27
Wohnort: Dortmund

@__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
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Ein schneller Blick in die Dokumentation zeigt, dass psutil extra eine Funktion hat, um auf das beenden von Prozessen zu warten.
Benutzeravatar
Domroon
User
Beiträge: 104
Registriert: Dienstag 3. November 2020, 10:27
Wohnort: Dortmund

@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:
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

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
Antworten