2011-07-27 7 views
17

Wiem, że możliwe jest konsekwentne przepisywanie ostatniej linii wyświetlanej w terminalu za pomocą "\ r", ale mam problem z ustaleniem, czy istnieje sposób, aby wrócić i edytować poprzedni linie drukowane w konsoli.Python - Przepisz wiele linii w konsoli

Chciałbym ponownie wydrukować wiele wierszy dla RPG z tekstem, jednak przyjaciel również zastanawiał się nad tym w przypadku aplikacji, która miała jedną linię poświęconą pasku postępu, oraz inną opisującą pobranie.

czyli konsola będzie drukować:

Moving plik: NameOfFile.txt
Razem Postęp: [########] 40%

a następnie zaktualizować odpowiednio (na obu liniach) w trakcie działania programu.

+1

Co platforma to ma być dalej? –

+0

Unix, w szczególności Fuduntu, ale chciałbym, żeby działał na większości platform ... Nie musi tak być. – JRJurman

+0

http://stackoverflow.com/questions/3002085/python-to-print-out-status-bar-and-percentage Dobra odpowiedź, pomógł mi załadować! –

Odpowiedz

28

W systemie Unix użyj modułu curses.

W systemie Windows istnieje kilka możliwości:

prosty przykład za pomocą klątw (Jestem całkowitym przekleństwem n00b):

import curses 
import time 

def report_progress(filename, progress): 
    """progress: 0-10""" 
    stdscr.addstr(0, 0, "Moving file: {0}".format(filename)) 
    stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress)) 
    stdscr.refresh() 

if __name__ == "__main__": 
    stdscr = curses.initscr() 
    curses.noecho() 
    curses.cbreak() 

    try: 
     for i in range(10): 
      report_progress("file_{0}.txt".format(i), i+1) 
      time.sleep(0.5) 
    finally: 
     curses.echo() 
     curses.nocbreak() 
     curses.endwin() 
+0

Dzięki, dodałem link w odpowiedzi. Czy API jest podobne do przekleństw Uniksa? – codeape

+1

W rzeczywistości jest moduł do robienia tego, co chcesz: [pasek postępu] [http://code.google.com/p/python-progressbar/] –

+0

Cóż, ale jak wyświetlać wiersze statusu nie na górze ekranu, ale na dno (w następnym wierszu po poprzednim wydruku). Chcę uzyskać efekt podobny do wielokrotnego 'pv --name' w jednym potoku –

2

Ostatecznie, jeśli chcesz manipulować ekran, trzeba korzystać z podstawowych bibliotek OS, który będzie typowo:

  • przekleństwa (lub bazowe zaciskowe kody sterujące jak śledzone przez terminfo/baza danych termcap) w systemie Linux lub OSX
  • Interfejs API konsoli win32 w systemie Windows.

Odpowiedź od @codeape już daje ci wiele z wielu opcji, jeśli nie masz nic przeciwko trzymaniu się jednego systemu operacyjnego lub z przyjemnością instalujesz biblioteki stron trzecich w systemie Windows.

Jeśli jednak potrzebujesz rozwiązania wieloplatformowego, które możesz zainstalować po prostu, możesz użyć asciimatics. W ramach rozwijania tego pakietu musiałem rozwiązać różnice między środowiskami, aby zapewnić pojedynczy interfejs API działający na systemach Linux, OSX i Windows.

Aby uzyskać paski postępu, można użyć obiektu BarChart, jak pokazano w this demo, używając this code.

+1

Jestem nieco zaskoczony, że coś takiego użyteczne jako manipulacja konsolą na różnych platformach nie jest dostarczana z pythonem. (Esp. Biorąc pod uwagę istnienie Tkintera) – PythonNut

+1

@ PythonNut - nie znam pełnej historii, ale AFAIK nikt nie był przygotowany do napisania obsługi kompatybilnego API dla Windows, a więc [rekomendacja] (https: // docs. python.org/3/howto/curses.html) było użycie różnych wymienionych już opcji kodu do kleju. –

1

Oto moduł Pythona zarówno Python 2/3, który można po prostu rozwiązać taką sytuację z kilku linii kodu; D

reprint - A simple module for Python 2/3 to print and refresh multi line output contents in terminal

można traktować po prostu jako przykład, że output normalny dict lub list (w zależności od używanego trybu).Podczas modyfikacji tych treści na przykład output, wyjście na terminalu zostanie automatycznie odświeżona: D

do potrzeb użytkownika, oto kod:

from reprint import output 
import time 

if __name__ == "__main__": 
    with output(output_type='dict') as output_lines: 
     for i in range(10): 
      output_lines['Moving file'] = "File_{}".format(i) 
      for progress in range(100): 
       output_lines['Total Progress'] = "[{done}{padding}] {percent}%".format(
        done = "#" * int(progress/10), 
        padding = " " * (10 - int(progress/10)), 
        percent = progress 
        ) 
       time.sleep(0.05) 
+0

Kiedy próbuję 'output_lines ['one'] = 'abcd'', po ustawieniu tak, jak zrobiłeś, otrzymuję błąd braku podziału. Uważam, że coś tu jest nie tak. Czy masz wgląd w to? – cat40

+0

@ cat40 Myślę, że to może coś sprawi, że 'get_terminal_size()' zwróci wartość (0,0). Czy mogę prosić o więcej szczegółów? Możesz opublikować w Github: D – Yinzo