Seite 1 von 1

Counter ersetzt alte zahl

Verfasst: Mittwoch 25. März 2009, 10:35
von sstm
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?

Verfasst: Mittwoch 25. März 2009, 10:59
von CM
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

Verfasst: Mittwoch 25. März 2009, 11:06
von sstm
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.

Verfasst: Mittwoch 25. März 2009, 11:09
von CM
Mach doch mal copy & paste vom ganzen Code.

Verfasst: Mittwoch 25. März 2009, 11:13
von sstm
Hab ich gemacht, schreibt die Zahlen aber immer noch in eine Reihe.

--
Hier mal ein screenshot:
Bild

Verfasst: Mittwoch 25. März 2009, 11:46
von Mad-Marty
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.

Verfasst: Mittwoch 25. März 2009, 11:54
von Trundle
Mit einem Wagenrücklauf sollte das in der Regel schon funktionieren, nur vielleicht nicht in IDLE.

Verfasst: Mittwoch 25. März 2009, 12:14
von sstm
Jetzt wo du es sagst, im Terminal funktionierts, Danke :D

Verfasst: Mittwoch 25. März 2009, 12:16
von jens
btw. geht in SciTE leider auch nicht...

Verfasst: Mittwoch 25. März 2009, 12:22
von CM
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

Verfasst: Mittwoch 25. März 2009, 13:14
von sstm
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

Verfasst: Mittwoch 25. März 2009, 13:28
von CM
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

Verfasst: Mittwoch 25. März 2009, 14:11
von sstm
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?

Verfasst: Mittwoch 25. März 2009, 14:36
von jens
vergleich doch beide Blöcke... Im ersten sehe ich kein "\r" und kein .flush() ;)

Verfasst: Mittwoch 25. März 2009, 14:39
von sstm
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?

Verfasst: Mittwoch 25. März 2009, 15:00
von CM
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'

Verfasst: Mittwoch 25. März 2009, 15:08
von jens
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...