Scheduling function calls in a Python curses UI

北城以北 提交于 2020-01-06 05:06:07

问题


I'm trying to write a program that will have a curses interface (so I can easily change settings on the fly) and will also be able to call and display the output of functions called on different schedules.

I can't figure out how to efficiently call something on a set time period and still use a curses loop that can take input at any time.

Here's an example of a small program that attempts to do what I'm saying. (doesn't work)

import curses, sched, time

from datetime import datetime

def show_time(sc):
    screen.addstr(12, 12, datetime.now())
    sc.enter(1, 1, show_time, (sc,))

screen = curses.initscr()
curses.noecho()
curses.curs_set(0)
screen.keypad(1)

screen.addstr("This is a Sample Curses Script\n\n")

s = sched.scheduler(time.time, time.sleep)
s.enter(1, 1, show_time, (s,))
s.run()
while True:
   event = screen.getch()
   if event == ord("q"): break

curses.endwin()

Thanks!


回答1:


Your script seems to have two problems.

  1. This line:

    screen.addstr(12, 12, datetime.now())
    

    will raise a TypeError since addstr expect a str not a datetime, so you need to replace that line with something like:

    screen.addstr(12, 12, time.strftime("%a, %d %b %Y %H:%M"))
    
  2. The second problem is that recursive sched calling:

    sc.enter(1, 1, show_time, (sc,))
    

    I never used the sched module, but I expanded my knowledge a bit and it seems that the .run() will stop untill all the scheduled events are completed.

If you're only interested in updating your screen every second, why don't you try something like:

import curses
import time
import threading

def update_time(screen):
    while 1:
        screen.addstr(12, 12, time.strftime("%a, %d %b %Y %H:%M:%S"))
        screen.refresh()
        time.sleep(1)

screen = curses.initscr()
curses.noecho()
curses.curs_set(0)
screen.keypad(1)

screen.addstr("This is a Sample Curses Script\n\n")
screen.refresh()

clock = threading.Thread(target=update_time, args=(screen,))
clock.daemon = True
clock.start()
while 1:
    event = screen.getch()
    if event == ord("q"):
        break

curses.endwin()



回答2:


I think that the best way to solve this is to use GNU readline for your input rather than the default curses input. Then use the async capability of readline so that you have a select loop from which you can call functions.

First of all, the Python readline library doesn't support async readline function calls, however it is easy to interface Python directly to readline using ctypes.

That way you have a select loop that is always in control. When there is no input, check the clock to see if it is time to run your function. If not, sleep for a few milliseconds, check for a keystroke, look at the clock and sleep again. time.sleep can handle fractional seconds.



来源:https://stackoverflow.com/questions/9281906/scheduling-function-calls-in-a-python-curses-ui

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!