Counter ersetzt alte zahl

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
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Hi,

ich hab ein kleines problem mit einem counter:

Code: Alles auswählen

def counter(start=10,ende=0,zeit=1):
    while start > ende:
        print start
        start -= 1
        time.sleep(zeit)
Dieser schreibt aber die neue Zahl immer in eine neue zeile, ich will aber nur die alte Zahl überschreiben. Wie geht das?
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hallo und willkommen im Forum!

z. B. so:

Code: Alles auswählen

import sys
import time

def counter(start=10,ende=0,zeit=1):
    while start > ende:
        sys.stdout.write("%d " % start)
        start -= 1
        time.sleep(zeit)
        sys.stdout.write('\r')
        sys.stdout.flush()

if __name__ == "__main__":
    counter(zeit=0.1)
Gruss,
Christian
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Das schreibt die Zahlen aber nur hintereinander:

Code: Alles auswählen

>>> 
10 9 8 7 6 5 4 3 2 1 
Ich will doch aber das zb die 9 die 10 ersetzt, die 8 die 9 usw.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mach doch mal copy & paste vom ganzen Code.
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Hab ich gemacht, schreibt die Zahlen aber immer noch in eine Reihe.

--
Hier mal ein screenshot:
Bild
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Das geht so einfach nicht.

Dafür musst du entweder die entsprechenden Terminal codes mitsenden für "gehe 1 zeichen zurück" oder aber eine Terminalhandling bibliothek nehmen, z.b. Curses.

Im IDLE wird das aber auf jeden fall nicht gehen sondern nur auf einer shell/cmd.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Mit einem Wagenrücklauf sollte das in der Regel schon funktionieren, nur vielleicht nicht in IDLE.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Jetzt wo du es sagst, im Terminal funktionierts, Danke :D
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

btw. geht in SciTE leider auch nicht...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

arrgh. IDLE ... und SciTE wundert mich auch nicht so ganz: Was ist denn da jeweils stdout? (Bzgl. IDLE: Wirf mal die Forumssuche an, um zu lernen, warum IDLE nicht deine 1. Wahl bleiben sollte.)

Bzgl. curses: Das ist eine Alternative - allerdings "etwas" aufwendiger und auch nicht ganz portabel.

Gruß,
Christian
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Jetzt ist noch ein kleine kleiner Fehler im skript, hier mal ein kurzer Ausschnitt der Ausgabe:

Code: Alles auswählen

...
11 Sekunden
10 Sekunden
9 Sekundenn
8 Sekundenn
...
Wenn die Zahl um eine stelle kleiner wird, dann steht am Ende noch das was darunter war, also was muss ich denn da noch ändern?

ps: IDLE nimm ich eigentlich eh nie her, ich bin mehr so ein gedit Mensch ;D
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Du kannst entweder genauer steuern, in dem Du ein Zeichen zurückgehst: '\b' - oder Vielfache davon. Oder Du setzt den String anders:

Code: Alles auswählen

"%2d" % start
Falls Du den Code nicht verstehst, solltest Du Dir nochmal das Tutorial antun.

Willst Du eine progress bar für Arme bauen? Da gibt es viele Beispiele im Forum.

Gruß,
Christian
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Mit der Formatierung geht's, mit dem Zeichen zurück funktioniert es aber nicht so wie ich mir das vorgestellt habe, da wird immer in eine neue Zeile geschrieben:

Code: Alles auswählen

import time
from sys import stdout

----------// geht nicht

def counter(start=20,ende=0,zeit=1):
	while start > ende:
		str_sekunden = " Sekunden"
		zurueck = (len(str_sekunden) + len(str(start))) * '\b'
		ausgabe = zurueck + str(start) + str(str_sekunden)
		stdout.write("%s" % ausgabe)
		start -= 1
		time.sleep(zeit)
		
if __name__ == "__main__":
	counter()
	
----------// geht

def counter(start=20,ende=0,zeit=1):
	while start > ende:
		stdout.write("%2d Sekunden" % start)
		stdout.write('\r')
		stdout.flush()
		start -= 1
		time.sleep(zeit)
		
if __name__ == "__main__":
	counter()
Was mach ich denn bei der ersten falsch?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

vergleich doch beide Blöcke... Im ersten sehe ich kein "\r" und kein .flush() ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sstm
User
Beiträge: 7
Registriert: Mittwoch 25. März 2009, 10:30

Das müsste doch durch das "\b" erstetzt werden oder etwa nicht?

----

Habe mal einen test gemacht:

Code: Alles auswählen

string1 = "grosser string"
string2 = "kl string"
zurueck = len(string1) * "\b"
print string1 + zurueck + string2
Und hier wird string1 überschrieben, leider wieder falsch:

Code: Alles auswählen

kl stringtring
Den string1 zu löschen geht wohl nicht, der wird immer nur mit string2 überschrieben, oder?
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

So geht's:

Code: Alles auswählen

import sys
import time
import string

def counter(start = 10, ende = 0, zeit = 1):
    str_sekunden = " Sekunden"
    while start > ende:
        zurueck = (len(str_sekunden) + len(str(start))) * '\b'
        ausgabe = zurueck + string.rjust(str(start), 2) + str_sekunden
        sys.stdout.write("%s" % ausgabe)
        sys.stdout.flush()
        start -= 1
        time.sleep(zeit)
Aber der Code ist jetzt nun wirklich grausig.

Bei '\r' wird nichts "überschrieben", sondern nur der Cursor neu positioniert. Lies mal diesen Artikel: http://de.wikipedia.org/wiki/Steuerzeichen

Gruß,
Christian

edit: Natürlich so:

Code: Alles auswählen

zurueck = ((len(str_sekunden) + len(str(start))) + 1) * '\b'
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich würde es so machen:

Code: Alles auswählen

def counter(start=20,ende=0,zeit=1):
    while start > ende:
        stdout.write('\r')
        stdout.write("%2d Sekunden               " % start)
        stdout.flush()
        start -= 1
        time.sleep(zeit) 
Einfach am Ende ein paar Leerzeichen mit ausgeben und gut. Dürfen natürlich nicht zu viele sein, damit keine neue Zeile entsteht...
Halte das aber für viel einfacher als \b zu nutzten...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten