Probleme mit Wagenrücklauf beim erstellen eines Countdowns

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
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

Hallo liebe Gemeinde,

ich bin grade dabei einen Countdown zu basteln und möchte das mir die Zeit in der Konsole angezeigt wird.
Hierbei möchte ich, das es immer in der selben Zeile geschieht. Hierbei benutze ich nun die Escapesequenze "\r".
So wie ich das verstanden habe setzt dies den Cursor ja an den Anfang der Zeile zurück. Leider wird bei mir aber nichts angezeigt.
Nur die letzte Zeile bekomme ich zu Gesicht. Zuerst dachte ich, das "\r" nicht nur zum Anfang springt, sondern die Zeile auch löscht.
Dann verstehe ich aber nicht, wieso ich die letzte Zahl zu Gesicht bekomme.
Tut mir leid wenn ich euch mit so einer banalen Frage belästige.
Hier einfach mal mein Anfang

Code: Alles auswählen

#!/usr/bin/env python

from time import sleep

ms = 60
while True:
    sleep(0.05)
    ms = ms - 1
    print "00:00:{}\r".format(ms),
    if ms == 0:
        break
[/code]

Gruß
Andi
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Avantasia1975: Zeilen werden normalerweise erst angezeigt, wenn sie mit einem Zeilenumbruch '\n' abgeschlossen werden. »flush« hilft.

Code: Alles auswählen

#!/usr/bin/env python
import sys
import time
for ms in xrange(60,-1,-1):
    time.sleep(0.05)
    sys.stdout.write("00:00:{}\r".format(ms))
    sys.stdout.flush()
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

Ahh ok.
Vielen Dank.
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

Sorry wenn ich das hier nochmal aufwärme.
Beim letzten mal habe ich das so hingenommen und mich gefreut, dass es geklappt hat.
Nun möchte ich es aber verstehen ;-)

Kann das mal einer für Dummie's erklären?

So wie ich das verstehe wird erstmal alles in einen Buffer aufgenommen und erst bei einem \n bzw "enter" gesendet wird.
Was bewirkt flush nun an der Stelle?
Wenn ich eine Zeile
print "Bla",
habe sende ich doch auch kein \n aber dennoch wird die Zeile angezeigt.
So wie Sirius3 es geschrieben hat, hat es ja dann geklappt und ich kann die Zeit sehen.
Wenn ich allerdings ein
python -c "import sys,time;sys.stdout.write('Hallo\r');sys.stdout.flush()"
ausführe kann ich das "Hallo" nicht sehen. Wieso kann ich aber die Zahl in dem Script sehen? Sollte die Ausgabe nicht von flush gelöscht werden?

Fragen über Fragen.
Ich hoffe mir kann das jemand halbwegs verständlich erklären.

Gruß Andi



Ok ich glaube ich habe es langsam.
Flush leer den buffer und schreibt den inhalt nach stdout.
Das hier kein \n Zeichen kommt, kann \r greifen.
Soweit richtig?
Zuletzt geändert von Avantasia1975 am Dienstag 24. September 2013, 19:54, insgesamt 1-mal geändert.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Avantasia1975 hat geschrieben:Wenn ich allerdings ein
python -c "import sys,time;sys.stdout.write('Hallo\r');sys.stdout.flush()"
ausführe kann ich das "Hallo" nicht sehen.
Du kannst das "Hallo" nicht sehen, weil alles zu schnell geht... ;-) Zuerst wird "Hallo" geschrieben, danach wird auf den Zeilenanfang gesprungen, danach wiederum übernimmt das Terminal und überschreibt das "Hallo".

Versuche mal folgendes, dann siehst Du es (zudem hat das importierte `time` dann auch einen Sinn ;-) ):

Code: Alles auswählen

python -c "import sys,time;sys.stdout.write('Hallo\r');sys.stdout.flush();time.sleep(1)"
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@Avantasia1975: Die Ausgabe wird in einen Pufferspeicher geschrieben und erst rausgeschrieben wenn entweder ein '\n' in dem Puffer landet, oder der Puffer voll ist, oder `flush()` ausgeführt wird (, oder `close()` was ein `flush()` impliziert).

Bei ``print 'Blah',`` siehst Du das Blah normalerweise nicht. Nur wenn das Programm zuende ist, denn dann wird natürlich auch der Puffer gelehrt weil am Ende auf allen offenen Dateien `close()` aufgerufen wird (zumindest auf Systemebene, nicht unbedingt die `close()`-Methode). Wenn die letzte Ausgabe auf `sys.stdout` ein ``print`` mit einem Komma am Ende war greift noch die besonderheit, dass der Pythoninterpreter beim beenden dann noch ein '\n' ausgibt. Aber nur wenn man ``print`` verwendet hat, nicht wenn man direkt mit `sys.stdout.write()` geschrieben hat.

Bei dem ``python -c …``-Beispiel wird also sehr wohl 'Hallo' ausgegeben und dann wird der Cursor auf den Anfang der Zeile gesetzt und das Programm endet. Und der Prompt vom Betriebssystem überschreibt dann das 'Hallo'. Gib da mal was aus was länger als der Prompt ist, und Du wirst nach dem Prompt den Rest davon sehen.
Avantasia1975
User
Beiträge: 18
Registriert: Sonntag 19. Mai 2013, 15:26

Super vielen Dank.

Ich hatte dann selber mal ein sleep ans Ende gesetzt und dann eben das "Hallo" gesehen.

Das beim schliessen bzw, beenden eines Programms quasi automatisch ein \n gesetzt wird erklärt das also.

Nu ist das alles klar.

Vielen Dank für die schnellen Antworten und einen schönen Abend noch.
Gruß
Andi
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Avantasia1975 hat geschrieben:Das beim schliessen bzw, beenden eines Programms quasi automatisch ein \n gesetzt wird erklärt das also.
[korinthenkackerei]Stimmt so nicht ganz. Du gibst 'Hallo' aus und setzt den Cursor an den Anfang der Zeile zurück. Beim Beenden des Programms steht der Cursor weiterhin dort. Nun schreibt Deine Shell den prompt-Text ab der aktuellen Cursorposition. Ein automatisches '\n' wird weder vom Programmende noch von der Shell initiiert.[/korinthenkackerei]
Das alles gilt, solange Du, wie in Deinem Beispiel, nicht `print` verwendest sondern Deine Ausgabe direkt an `sys.stdout` schickst. Wie `print` arbeitet hat Dir ja BlackJack schon erklärt.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten