问题
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.
This line:
screen.addstr(12, 12, datetime.now())
will raise a
TypeError
sinceaddstr
expect astr
not adatetime
, so you need to replace that line with something like:screen.addstr(12, 12, time.strftime("%a, %d %b %Y %H:%M"))
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