2012-12-22 14 views
6

Napisałem program curses w python. Działa dobrze. Jednakże, kiedy używam nodelay(), program wychodzi od razu po uruchomieniu w terminalu, z niczym nie pokazanym (tylko nowym monitem).nodelay() powoduje, że program Python Curses opuścił

EDIT

Kod ten będzie odtworzyć błąd:

 
sc = curses.initscr() 

sc.nodelay(1) # But removing this line allows the program to run properly 

for angry in range(20): 
     sc.addstr(angry, 1, "hi") 

Oto mój pełny kod

 
import curses, time, sys, random 

def paint(x, y, i): 
     #... 
def string(s, y): 
     #... 

def feed(): 
     #... 

sc = curses.initscr() 
curses.start_color() 
curses.curs_set(0) 
sc.nodelay(1) ######################################### 

# vars + colors inited 

for angry in range(20): 
     try: 
       dir = chr(sc.getch()) 

       sc.clear() 

       feed() 

       #lots of ifs 

       body.append([x, y]) 
       body.pop(0) 

       for point in body: 
         paint(*point, i=2) 

       sc.move(height-1, 1) 
       sc.refresh() 
       time.sleep(wait) 

     except Exception as e: 
       print sys.exc_info()[0], e 

sc.getch() 
curses.beep() 

curses.endwin() 

Dlaczego to happenning i jak mogę użyć nodelay() bezpiecznie?

+1

Spróbuj sparować swój kod do minimum niezbędnego do odtworzenia błędu. Na przykład można ustawić nodelay(), a następnie przejść do nieskończonej pętli, która łamie i kończy się, gdy getch() klucz. Jeśli błąd zniknie w minimalnym przypadku testowym, wymyśl, co się zmieniło. Jeśli to nie pomoże opublikować wadliwy test. – Philip

+0

@Philip dobre myślenie, zrobiłem to i opublikowałem wyniki. – ACarter

Odpowiedz

5

mam przepisany swoją minified demo, aby uzyskać podstawową funkcjonalność roboczą. Ma nonblocking getch(). Jeśli trzymasz klawisz Q, gdy wywoływane jest getch(), program się kończy, w przeciwnym razie pętla będzie kontynuowana.

import curses, time 

def main(sc): 
    sc.nodelay(1) 

    for angry in range(20): 
     sc.addstr(angry, 1, "hi") 
     sc.refresh() 

     if sc.getch() == ord('q'): 
      break 

     time.sleep(1) 

if __name__=='__main__': 
    curses.wrapper(main) 

Najistotniejszą zmianą zrobiłem korzysta curses.wrapper uzyskać kontekst ekran zamiast korzystania curses.initscr(). Zaletą jest to, że jeśli twój program trafi na nieprzechwycony wyjątek (na przykład uderzając^C), to cofa wszystkie zmiany, które zrobiłeś terminalowi, jak wyłączanie kursora przed wyjściem. Bardzo pomaga podczas debugowania.

Z tego miejsca zalecam dodanie funkcji programu z powrotem w bardzo małych krokach. Klątwy to rodzaj bólu, z którym można pracować, a jeśli dokonasz wielu zmian naraz, trudno jest ustalić, które z nich spowodowało załamanie. Powodzenia!

+1

Rozwiązany. Dodanie głównego opakowania pozwoliło mi zobaczyć, że wychodziłem z powodu błędu, gdy 'getch()' nie zwróciło nic (ponieważ żadne dane wejściowe nie były dostępne) i próbowano umieścić go w 'chr()', który nie może obsłużyć nic. Dzięki za pomoc, będzie to bardzo przydatne przy rozwiązywaniu innych błędów. – ACarter

0

widzę żadnej różnicy podczas prowadzenia małego programu testowego z lub bez linijka sc.nodelay().

Ani sprawa wydrukowanie czegokolwiek na ekranie ...

+0

Chodzi o to, że dla mnie, z 'sc.nodelay()', okna curses nie są nawet otwarte, a więc nie mogę nic zrobić, ponieważ nie ma na co to zrobić. – ACarter