0

I faced with behavior which I cannot understand.

import curses
import time

myscreen = curses.initscr()

y, x = myscreen.getmaxyx()
i = 0

while y >= 24 and x >= 80 and i <= 23:
    myscreen.addstr(i, 0, 'Python curses in action!')
    myscreen.refresh()
    y, x = myscreen.getmaxyx()
    i += 1
    time.sleep(1)

curses.endwin()

This code will write 24 strings with 1 second interval and it's ok. But when I will begin to change size of terminal window during execution, strings will appear on screen much faster then 1 string per second. Could you please explain this behavior and maybe get advice how to "protect" my time.sleep()? Thanks.

P.S. without curses sleep() works fine.

2 Answers2

1

When you resize your terminal, the terminal emulator sends a signal (SIGWINCH) to the program(s) using it for input/output. In your example, that interrupts time.sleep().

Rather than use time.sleep(), you could use the curses function napms() (which waits a given number of milliseconds).

Starting with your current program, you can see the time-behavior better if you print it out (adapting an answer from Get current time in milliseconds in Python?):

import curses
import time
from datetime import datetime
from datetime import timedelta

start_time = datetime.now()

# returns the elapsed seconds since the start of the program
def elapsed():
   dt = datetime.now() - start_time
   ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
   return ms / 1000.0

myscreen = curses.initscr()

y, x = myscreen.getmaxyx()
i = 0

while y >= 24 and x >= 80 and i <= 23:
    myscreen.addstr(i, 0, 'Python curses in action ' + "%.3f" % elapsed())
    myscreen.refresh()
    y, x = myscreen.getmaxyx()
    i += 1
    time.sleep(1)

myscreen.getch()
curses.endwin()

curses has a function like sleep, but in milliseconds: napms. Using that, you'll get more more consistent behavior, because ncurses handles the SIGWINCH, restarting the napms as needed to get the requested time-delay. When I change that time.sleep(1) to

    curses.napms(1000)

the program continues to "sleep" for one second while the terminal is resized.

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
0

From the documentation of time.sleep():

Suspend execution of the current thread for the given number of seconds. The argument may be a floating point number to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.

Klaus D.
  • 13,874
  • 5
  • 41
  • 48