2

I'm creating a curses terminal GUI using Python but the first I start the script and I stop it, the terminal output is totally broken. Every new lines are printed after the length of the previous one.

For example:

self.player_screen()                                                                                                                                                                                                                                                                                          │
│                                   File "main.py", line 76, in player_screen                                                                                                                                                                                                                                            │
│                                                                                   for player_state in player:                                                                                                                                                                                                             │
│                                                                                                                File "/home/jerome/PycharmProjects/project/main.py", line 40, in current_play                                                                                                                            │
│                                                                                                                                                                                                   sleep(1)                                                                                                                │
│                                                                                                                                                                                                           KeyboardInterrupt

I don't find why the terminal output is broken and how to fix this. I use the Python curses package like the doc say:

def login_screen(self):
    login_title = "Please login using your username/id:\n"
    login_screen = newwin(0, 0)
    login_screen.box()
    v_dim, h_dim = login_screen.getmaxyx()

    login_screen.addstr(round(v_dim / 2), round((h_dim - len(login_title)) / 2), login_title)

    username_input = login_screen.subwin(1, 44, round(v_dim / 2 + 1), round((h_dim - 44) / 2))
    username_text_input = textpad.Textbox(username_input)
    username_input.refresh()

    login_screen.addstr(v_dim - 1, h_dim - 20, "[Enter]Submit")
    login_screen.refresh()

    username = username_text_input.edit()

    endwin()

I don't find anything wrong in my code an nothing the helped me inside the doc.

Did someone already had this problem and solved it?

Jérôme
  • 1,966
  • 4
  • 24
  • 48
  • I think your application is crashing or you are using other ncurses functions after the endwin. See: https://stackoverflow.com/questions/11753909/clean-up-ncurses-mess-in-terminal-after-a-crash – Wolfeius Aug 06 '19 at 13:38
  • 1
    Possible duplicate of [Clean up ncurses mess in terminal after a crash](https://stackoverflow.com/questions/11753909/clean-up-ncurses-mess-in-terminal-after-a-crash) – Wolfeius Aug 06 '19 at 13:38
  • 1
    `curses` necessarily changes various terminal parameters in order for it to do its job. If your program terminates due to an error, it never gets a chance to undo those changes. You either need to use `try`..`finally` to make sure the shutdown *always* gets done, or use `curses.wrapper()` to execute your main function which basically accomplishes the same thing. – jasonharper Aug 06 '19 at 13:39
  • I have the same problem if I call a script that do some `print` inside the curses window, however no error are thrown inside this script – Jérôme Aug 06 '19 at 13:42
  • The sample code is not complete enough to see the problem (you should provide a [MCVE](https://stackoverflow.com/help/minimal-reproducible-example)). – Thomas Dickey Aug 06 '19 at 19:50

2 Answers2

3

Consider wrapping your code using a curses wrapper().

From the docs:

A common problem when debugging a curses application is to get your terminal messed up when the application dies without restoring the terminal to its previous state. In Python this commonly happens when your code is buggy and raises an uncaught exception. Keys are no longer echoed to the screen when you type them, for example, which makes using the shell difficult.

In Python you can avoid these complications and make debugging much easier by importing the curses.wrapper() function and using it like this:

from curses import wrapper

def main(stdscr):
    # Clear screen
    stdscr.clear()

    #Insert your code here

wrapper(main)
blackbrandt
  • 2,010
  • 1
  • 15
  • 32
0

Your program seems to be raising an exception.

Wrap your curses code in a try/catch to quit nicely. For example:

try:
    [your curses code here]
except:
    curses.nocbreak()
    stdscr.keypad(0)
    curses.echo()
    curses.endwin()
    raise

The last raise should print the exception in the console as usual.

I wrote a utility module which does this for me, it's there.

Tim
  • 2,052
  • 21
  • 30