String kürzen

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

Sonntag 25. Januar 2015, 18:00

@wusa: Die Ausgabe vom ``ls`` wird nicht ausgelesen, dadurch könnte der Aufruf blockieren und damit würde ``ls`` nicht zuende durchlaufen.

Und wenn das tatsächlich der gesamte Code ist und es nicht blockiert, dann endet ja der Python-Prozess und damit werden auch die Kindprozesse beseitigt.

Edit: Wenn man mal ein `time.sleep()` nach dem `Popen()` einfügt, sieht das so aus:

Code: Alles auswählen

bj@god:~$ ps
  PID TTY          TIME CMD
 7510 pts/5    00:00:00 python
 7511 pts/5    00:00:00 ls <defunct>
 7512 pts/5    00:00:00 ps
Sirius3
User
Beiträge: 8270
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 25. Januar 2015, 18:16

@wusa: wenn ein Programm beendet wird, wird der init-Prozess automatisch Vater aller Kindprozesse, und init räumt Zombies sofort ab.
wusa
User
Beiträge: 21
Registriert: Dienstag 18. Februar 2014, 11:08

Sonntag 25. Januar 2015, 18:44

Sorry für das blöde Nachfragen, aber ich verstehe es nicht.

Code: Alles auswählen


import subprocess
import time
command = subprocess.Popen(['ls'], stdout=subprocess.PIPE)
time.sleep(1)


Bringt folgende Ausgabe:

Code: Alles auswählen

 PID TTY          TIME CMD
 2234 pts/0    00:00:01 bash
 2345 pts/0    00:00:00 ps

BlackJack

Sonntag 25. Januar 2015, 19:38

@wusa: Du hast das ``ps`` auch ausgeführt *während* das andere Programm noch lief? Deswegen ist das `sleep()` da ja drin, damit man die Chance hat das zu sehen bevor das Skript zuende ist.
wusa
User
Beiträge: 21
Registriert: Dienstag 18. Februar 2014, 11:08

Montag 26. Januar 2015, 08:24

Ich habe "ps" nicht während "sleep()" aufgerufen!

Ich verstehe es leider nicht.
Wenn ich die paar Zeilen ausführe und dann KEINEN Rückgabewert erhalte, dann wurde doch der Prozess vermutlich auch wieder ordnungsgemäß beendet? Oder sehe ich das falsch?
Sonst müsste doch ein Prozesse bei "ps" auftauchen?

Ich hinterfrage das ganze leider nur, da ich es nicht verstehe. Sicherlich hat es auch was mit sauberer Programmierung zu tun.

Da aber bei der Ausgabe von "ps" nichts auftaucht, nach dem "sleep()" schließe ich daraus, dass hier nichts hängen bleibt?


Vorab schon mal Danke! für die Hilfe und evlt. auch die Geduld ;)
Sirius3
User
Beiträge: 8270
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 26. Januar 2015, 09:21

@wusa: dass Linux so freundlich ist, nach dem Ende eines Programms alle Zombies aufzuräumen, darf für Dich kein Grund sein, sich nicht um das Problem sauber zu kümmern.
BlackJack

Montag 26. Januar 2015, 09:27

@wusa: Während des `sleep()` existiert der Zombieprozess. Der verschwindet wenn Dein Programm endet. Das es einen Zombieprozess gibt, habe ich ja in einem Beitrag weiter oben demonstriert. Man sollte halt genau wie man Dateien schliesst so bald wie möglich nach dem man sie nicht mehr benötigt, auch dafür sorgen das Prozesse so kurz wie möglich im Zombiezustand bleiben. Andernfalls kann man in beiden Fällen wenn es blöd läuft an Begrenzungen vom Betriebssystem stossen die das Programm hart beenden.

Ergänzend zu Sirius: Du hast da ja auch kein Programm das sofort wieder endet, sondern erstellst in einer Schleife immer neue Prozesse. Vielleicht sogar in einem Programm welches lange läuft. Da käme das Betriebssystem ja erst ganz am Ende zum Zug um hinter dem Programm aufzuräumen. Und das Ende des Programms könnte wie gesagt dann auch vom Betriebssystem beendet werden statt regulär zu enden, ganz einfach weil alle Ressourcen aufgebraucht waren die dem Prozess zugestanden wurden.
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Montag 26. Januar 2015, 09:53

wusa hat geschrieben:Ich hinterfrage das ganze leider nur, da ich es nicht verstehe. Sicherlich hat es auch was mit sauberer Programmierung zu tun.
In Unixoiden Systemen werden Prozesse mittels fork geklont, was zunächst zu 2 fast identischen Prozessen führt. Der neue Prozess wird als Kindprozess des Ursprungprozesses geführt. Dieses Bootstrappen von Kindprozessen beginnt nach dem Booten des Systems mit dem Urvater aller Prozesse (init; der init-Prozess selbst wird vom Kernel initialisiert, da man von einem 0. Prozess schlecht forken kann) und führt zum bekannten Prozessbaum eines laufenden Systemes.
In Deinem Falle übernimmt subprocess das Forken (Duplizieren des Pythonprozesses als Kind) und Laden des neuen Binärcodes (exec* Syscalls).
Der Kernel weiss nun, ob ein Prozess beendet wurde oder nicht. Wenn er beendet wurde, werden Ressourcen freigeschaufelt (Speicher, Filedescriptoren etc.). POSIX sieht nun vor, dass der Kindprozess dem Elternprozess einen Rückgabewert von 0-255 gibt (die Idee eines Rückgabewertes eines Prozesses ist allerdings viel älter), was z.B. eine simple Erfolgskontrolle möglich macht.
Da der Kernel kein Wissen darüber hat, wann den Elternprozess der Rückgabewert des Kindes interessiert, speichert er den Wert selber bis er vom Elternprozess angefragt wird. Wird er nie angefragt (was der Kernel nicht wissen kann), ist der Speicher blockiert --> Zombie. Erst wenn auch der Elternprozess terminiert, ist klar, dass der Wert verworfen werden kann und der Zombie wird abgeräumt.
wusa
User
Beiträge: 21
Registriert: Dienstag 18. Februar 2014, 11:08

Montag 26. Januar 2015, 14:15

Vielen Dank für die ganzen Antworten!

Werde ich heute gleich mal umsetzen!
Antworten