Ausgabe aus Konsole holen

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.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Manchmal ist es wirklich hilfreich, wenn man ein wenig Tutorials durchmacht und Dokumentationen liest und ein wenig mitdenkt. Und "myarg" und "mycmd" stehen für "hier bitte etwas sinnvolles einsetzen".
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

See also: Where is the "Any Key"? :twisted:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

gut, das habe ich jetzt mittlerweile mal verstanden, so, jetzt hab ich ein größeres vorhaben^^

jetzt gibt es z.b.: programme, wie nehmen wir mal ping
wenn ich z.b.: ping google mache, dann bekomm ich ja in abständen immer wieder eine neue ausgabe also eine neue reihe ensteht im terminal.

wie kann ich jetzt für jedes mal, das eine neue zeile kommt, diese zeile die gerade kam auslesen, und von mir aus das time=xx.x ms aus

64 bytes from fg-in-f104.google.com (72.14.221.104): icmp_seq=11 ttl=247 time=54.8 ms
64 bytes from fg-in-f104.google.com (72.14.221.104): icmp_seq=12 ttl=247 time=50.7 ms
64 bytes from fg-in-f104.google.com (72.14.221.104): icmp_seq=13 ttl=247 time=45.1 ms
........
....

anzeigen lassen? und das bei jeder zeile neu auslesen die neu kommt?

ist das in diesem ausmaß überhaupt machbar?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Folgender Code fiele mir so auf die Schnelle ein:

Code: Alles auswählen

#! /usr/bin/python
# -*- coding: utf-8 -*-

from subprocess import Popen, PIPE
from time import time, sleep

def main():
    print "Starte ...\n"
    p = Popen(["ping", "www.google.de", "-w 3", "-i 2"], stdout=PIPE)
    while p.poll() is None:
        #print p.stdout.read(1),
        print "läuft noch", time()
        sleep(1)
    print "\nEnde"
    print "Ausgabe:"
    print p.stdout.read()

if __name__ == "__main__":
    main()
Allerdings kommt man so auch nicht permanent an die Ausgabe. Man kann zwar in der Schleife per p.stdout.read(100) ständig 100 Bytes aus dem "Stream" holen, aber dann muss man sich zumindest noch überlegen, wie man feststellt, dass eine "Zeile" der Ausgabe fertig ist. (die 100 ist nur ein Beispiel!)

So richtig "schön" wirds vermutlich nur durch die Benutzung von Threads. Einer startet den Prozess wie hier, ein anderer liest die Ausgabe permanent aus und verarbeitet sie weiter.

Zudem steht zu überlegen, wie man den Prozess zur Not killt!

Exception Handling fehlt da natürlich auch noch ...

EDIT: Zur Verarbeitung der Ausgabe bzw. dem Auswerten bestimmter Daten schau Dir mal Regular Expressions an! (Gibt nen gutes Howto in der Doku!)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Man sollte alle Parameter in eigene Elemente in der Liste schreiben, denn ``ping`` kennt kein ``-w 3`` Parameter sondern nur ``-w`` gefolgt von ``3``. Da gibt es keine High-Level zuordnung von Parameter zu wert, das erledigen dann Paring Libraries wie Getargs, POPT etc.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Stimmt! Ist ja eine Liste ... hatte mir Sorgen wegen der Reihenfolge gemacht, aber die ist ja bei einer Liste fest. Danke für den Hinweis ... ist schon arg spät ;-)
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

aber das ist leider nicht so ganz wie ich mir das vorgestellt hatte....
hatte das eher so gedacht, das eine zeile ein in eine variable kommt, und nicht die ganze ausgabe.

Ich wollte eig. nicht mein ganzes Vorhaben erklären, da es lang dauert und kompliziert ist, ich hab ein programm geschrieben, in dem man verschieden einstellungen macht und dateien auswählt sobald man das gemacht hat, wird ein befehl erstellt, der ein programm im terminal starten lässt, der dieser sieht ungefähr so aus:

growisofs -use-the-force-luke=dao -use-the-force-luke=break:1913760 -dvd-compat -speed=%s -Z /dev/dvd=%s" % (speed, filename)

sobald dieser befehl abgeschickt ist (mit Popen), bekomme ich im terminal nacheinander diese ausgabe:

0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
0/7835492352 ( 0.0%) @0x, remaining ??:?? RBU 100.0% UBU 0.0%
3964928/7835492352 ( 0.1%) @0.9x, remaining 1185:07 RBU 100.0% UBU 7.0%
22544384/7835492352 ( 0.3%) @4.0x, remaining 225:15 RBU 100.0% UBU 90.8%
41123840/7835492352 ( 0.5%) @4.0x, remaining 135:49 RBU 100.0% UBU 90.8%
59670528/7835492352 ( 0.8%) @4.0x, remaining 99:54 RBU 100.0% UBU 90.8%
78217216/7835492352 ( 1.0%) @4.0x, remaining 80:59 RBU 100.0% UBU 90.8%
96763904/7835492352 ( 1.2%) @4.0x, remaining 70:38 RBU 100.0% UBU 90.8%
115343360/7835492352 ( 1.5%) @4.0x, remaining 62:28 RBU 99.9% UBU 90.8%
133890048/7835492352 ( 1.7%) @4.0x, remaining 56:33 RBU 100.0% UBU 90.8%
.........
.....
.........
7780892672/7835492352 (99.3%) @4.0x, remaining 0:10 RBU 100.0% UBU 90.8%
7799439360/7835492352 (99.5%) @4.0x, remaining 0:06 RBU 100.0% UBU 90.8%
7817986048/7835492352 (99.8%) @4.0x, remaining 0:03 RBU 52.2% UBU 90.8%


nun ist mein problem das ich zu diesem ganzen datenkram ein progressbar machen will, dazu brauche ich aber genau die prozentzahlen die mir im terminal aufgelistet werden.

so, wie kann ich nun, von mir auch alle 2 sekunden oder auch jede zeile egal wie. wie komme ich an diese prozentzahl heran?

Wäre echt suuper wenn mir dabei jemand helfen könnte.

Danke im Vorraus
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wie ich schon schrieb wird das wohl nur über Threads zu erreichen sein! Wobei das je nach GUI-Toolkit auch arg hakelig werden kann bzw. diese ggf. ihre eigenen Thread-Implementierungen mitbringen (wenn ich das soweit richtig verstanden habe bisher).

Bei wxWidgets gab es in deren Turorial / Wiki eine eigene Sektion für Threads innerhalb der GUI.

Ein Thread sollte eben diesen ganzen Subprozess-Kram handeln und der andere (GUI-Thread / Mainloop o.ä.) liest aus einer Queue des ersten Threads regelmäßig Daten aus und bereitet diese dann auf.

So könnte ich mir das gut vorstellen!

Allerdings ist das sicherlich alles andere als trivial für einen Anfänger.
BlackJack

Und der Text muss vom gestarteten Programm auf dessen `stderr` ausgegeben werden, sonst bekommt man wieder das Problem mit dem Puffern, was hier schon zig mal im Forum besprochen wurde und wo nur so etwas wie `pexpect` hilft. `groisofs` sollte aber auf `stdout` ausgeben und damit auf "seiner" Seite nach jeder Zeile "flush"en.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

gut, vom Prinzip her ist das ja schon mal recht klar, der eine Thread führt das Programm aus, von mir aus jetzt das growisofs, oder auch das ping google zum test, und dieser thread schick dann regelmäsig die NEU ENTSTDANDENE zeile von ping google aus und das haupsprogramm verarbeitet und bearbeitet dann diese zeile und gibt sie aus

zumindest sollte es vllt so sein.

Ich hab mir nun mal ein paar Grundlagen von threading durchgelesen, aber jetzt muss ich ja trorzdem es irgendwie schaffen, so dass das ping google in einem rutsch läuft und ich dann aber trotzdem jede neue zeile auslesen kann, wie schaffe ich das am besten? kann mir da vllt jemand ein wenig helfen?

ich muss halt jede neue zeile auslesen können, ohne einfluss auf den prozess ping google zu nehmen, also den prozess nicht zu stören.

wenn ich
pingaling = os.popen("myprozess")
line = pingaling.readline()

dann habe ich zwar eine zeile, aber der prozess wird ja so wie ich das verstanden habe gar nicht richtig ausgeführt, oder? sondern sozusagen nur bis zur ersten zeile, die mir dann auch angezeigt wird???


Ich hoffe mal mir ist niemand böse, das ich scheinbar noch so sehr wenig von dem subprocess und threading verstehe, aber es ist sehr wichtig, und ich hab mir versucht schon viel durchzulesen
BlackJack

@gugugs: Nein `ping` wird schon weiter ausgeführt, allerdings nur solange bis der oder die Puffer voll sind, die zwischen `ping` und Deinem Programm existieren, dann blockiert `ping`, weil es seine Ausgabe nicht mehr los wird. Wenn Du willst das Ping weiterläuft, musst Du schon kontinuierlich Zeilen lesen, damit es nicht blockiert.

Allerdings gibt's da wie gesagt, noch das Problem mit den Puffern, die Du nicht alle beeinflussen kannst. Wenn das gestartete Programm auf sein `stdout` ausgibt und das nicht mit einem Terminal verbunden ist, wird in der Regel ein Blockpuffer verwendet, d.h. Du bekommst immer wenn der voll ist, ein paar Zeilen ganz schnell hintereinander. `stderr` ist dagegen in der Regel zeilengepuffert.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

ach gott, das wird echt alles immer kompliziert, aber ich brauch das unbedingt^^

Würde sich jemand bereit erklären, mal einen mini kleinen beispiel code zu machen mit dem beispiel ping

also genau so, das der prozess läuft, und ich woanders, jede linie, einen bestimmten teil herausbearbeite z.b. das time=46.9

in

64 bytes from fg-in-f104.google.com (72.14.221.104): icmp_seq=1 ttl=247 time=46.9 ms

und das dann immer angezeigt wird

denn das ist alles so extrem theoretisch, wenn ich mal sehen würde wie das aussieht, würde mir das eeeiniges helfen.

Schon mal vielen Dank an alle die sich schon die Zeit genommen haben.
Antworten