2010-01-23 14 views
22

Niektóre aplikacje, takie jak hellanzb, mają sposób drukowania na terminalu z pojawieniem się dynamicznie odświeżających danych, takich jak top().Dynamiczne drukowanie terminali z pytonem

Co to jest najlepsza metoda w Pythonie do robienia tego? Przeczytałem o rejestrowaniu i przekleństwach, ale nie wiem, czego używać. Tworzę reimplementację topu. Jeśli masz inne sugestie, również jestem dla nich otwarty.

+5

Jaki jest powód, dla którego jest to wiki społeczności? – MitMaro

+0

Po prostu użyj 'print': http://stackoverflow.com/a/8436827/1959808 –

Odpowiedz

31

Najprostszy sposób, jeśli tylko kiedykolwiek trzeba aktualizować pojedynczą linię (na przykład, tworząc pasek postępu), jest użycie '\r' (powrót karetki) oraz sys.stdout:

import sys 
import time 

for i in range(10): 
    sys.stdout.write("\r{0}>".format("="*i)) 
    sys.stdout.flush() 
    time.sleep(0.5) 

Jeśli potrzebujesz odpowiedniego interfejsu konsoli, które obsługują przesuwając kursor itd użyć modułu curses od Standa rd biblioteka:

import time 
import curses 

def pbar(window): 
    for i in range(10): 
     window.addstr(10, 10, "[" + ("=" * i) + ">" + (" " * (10 - i)) + "]") 
     window.refresh() 
     time.sleep(0.5) 

curses.wrapper(pbar) 

Jest wysoce wskazane, aby korzystać z funkcji curses.wrapper nazwać swoją główną funkcję, będzie dbać o sprzątanie terminal w przypadku wystąpienia błędu, więc nie będzie w stanie nie do użytku później .

Jeśli utworzysz bardziej złożony interfejs użytkownika, możesz utworzyć wiele okien dla różnych części ekranu, pól wprowadzania tekstu i obsługi myszy.

+0

Właściwie nie musisz nawet używać' sys.stdout'. Instrukcja 'print 'hey',' nie utworzy podziału wiersza. – bgusach

0

Kiedy robię to w skryptach powłoki na Uniksie, zwykle używam czystego programu. Możesz użyć modułu podprocesu Python, aby go uruchomić. Przyniesie ci to przynajmniej to, czego szukasz szybko.

0
[[email protected] ~]$ ldd /usr/bin/top | grep curses 
     libncursesw.so.5 => /lib64/libncursesw.so.5 (0x0000003ae1400000) 

curses jest.

2

Brzmi jak zadanie dla curses. Jest to najczęściej używana biblioteka do układania i zarządzania ekranem w trybie tekstowym. Python ma bardzo dobre wsparcie dla przekleństw, w tym wsparcie dla paneli:

9

Jak większość odpowiedzi już zadeklarowała, naprawdę niewiele masz opcji na Linuksa, ale używasz ncurses. Ale co, jeśli nie jesteś w Linuksie, lub chcesz czegoś bardziej zaawansowanego do tworzenia terminalowego interfejsu użytkownika?

Osobiście uważam, że brak nowoczesnego, wieloplatformowego terminalu API w Pythonie jest frustrujący, więc napisałem asciimatics, aby rozwiązać ten problem. Nie tylko daje on simple cross-platform API, zapewnia również wiele wyższego poziomu abstrakcji dla UI widgets and animations, które mogą być łatwo wykorzystane do stworzenia najbardziej podobnego interfejsu użytkownika.

+0

asciimatyka jest świetna !! ^^ –

+0

Po prostu sprawdzam projekt i jest super! Dobra robota :) –

+0

Dzięki. BTW, mam teraz napisane przykładową aplikację [top] (https://github.com/peterbrittain/asciimatics/blob/master/samples/top.py) dla tego priject. –

1

Zhakowałem ten skrypt, używając curses. To naprawdę rozwiązanie ad-hoc, które zrobiłem dla zabawy. Nie obsługuje przewijania, ale myślę, że jest to dobry punkt wyjścia, jeśli chcesz zbudować monitor aktualizujący na żywo z wieloma wierszami na terminalu.

https://gist.github.com/tpandit/b2bc4f434ee7f5fd890e095e79283aec

0

Wysyłanie wyjście do terminala za pomocą polecenia print() mogą być wykonywane bez potrzeby przewijania w przypadku korzystania z „koniec” atrybutu.

Wartość domyślna to end = '\ n', która jest nową linią.

Aby wyłączyć przewijanie i zastąpić całą poprzednią linię, można użyć wyjścia RETURN, które jest "\ r".

Jeśli chcesz przepisać tylko cztery ostatnie znaki, możesz użyć kilku spacji.

print(value, "_of_", total, end='\r') 

UWAGA Działa to dla standardowego terminala systemu. Emulator terminalu w niektórych narzędziach, takich jak IDLE, ma błąd, a "\ r" nie działa poprawnie, dane wyjściowe są po prostu łączone z kilkoma niedrukowalnymi znakami.

BONUS INFORMACJA DLA print() W powyższym przykładzie, przestrzenie po obu stronach „z” mają zapewnić white-space między moimi wartościami i słowo „z”. Jednak domyślnym separatorem print() jest "" (spacja), więc kończymy na białej spacji między wartością i podkreśleniem "_of_".

>> print (value, "_of_", total, end='\r') 
8 _of_ 17 

Atrybut sepparator, sep, może służyć do ustawiania znaku między wydrukowanymi przedmiotami. W moim przykładzie zmienię go na ciąg pusty (''), aby mój wynik odpowiadał moim potrzebom.

>> print (value, "_of_", total, sep='', end='\r') 
8_of_17