在Python curses UI中调度函数调用
我正在尝试写一个程序,这个程序会有一个curses界面(这样我可以轻松地实时更改设置),同时还能够根据不同的时间安排调用函数并显示输出。
我搞不清楚怎么才能高效地在设定的时间间隔内调用某个东西,同时又能使用一个curses循环,这样就可以随时输入。
下面是一个小程序的例子,试图实现我说的功能。(但没有成功)
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()
谢谢!
2 个回答
0
我觉得解决这个问题的最好办法是用GNU readline来处理输入,而不是默认的curses输入。然后利用readline
的异步功能,这样你就可以有一个select
循环,从中调用函数。
首先,Python的readline库不支持异步的readline函数调用,不过用ctypes
直接把Python和readline连接起来是很简单的。
这样你就有了一个始终在控制中的选择循环。当没有输入时,可以查看时钟,看看是否该运行你的函数。如果还没到时间,就休眠几毫秒,检查一下是否有按键输入,然后再看看时钟,继续休眠。time.sleep
可以处理小数秒。
4
你的脚本似乎有两个问题。
这一行:
screen.addstr(12, 12, datetime.now())
会引发一个
TypeError
错误,因为addstr
需要的是一个str
类型的字符串,而不是datetime
类型的日期时间。所以你需要把那一行换成类似这样的:screen.addstr(12, 12, time.strftime("%a, %d %b %Y %H:%M"))
第二个问题是递归调用的调度:
sc.enter(1, 1, show_time, (sc,))
我之前没用过调度模块,但我稍微了解了一下,似乎
.run()
方法会一直停下来,直到所有安排的事件都完成。
如果你只是想每秒更新一次屏幕,为什么不试试这样的代码呢:
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()