简体   繁体   English

在Python curses UI中调度函数调用

[英]Scheduling function calls in a Python curses UI

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. 我正在尝试编写一个具有curses接口的程序(这样我就可以随时轻松地更改设置),并且还能够调用并显示在不同时间表上调用的函数的输出。

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. 我无法弄清楚如何在设定的时间段内有效地调用某些内容,而仍然使用curses循环,该循环可以随时接收输入。

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! 谢谢!

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: 由于addstr期望str不是datetime ,因此将引发TypeError ,因此您需要用以下内容替换该行:

     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. 我从未使用过sched模块,但是我扩展了我的知识,并且似乎.run()会停止直到所有计划的事件完成为止。

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()

I think that the best way to solve this is to use GNU readline for your input rather than the default curses input. 我认为解决此问题的最佳方法是对您的输入使用GNU readline,而不是默认的curses输入。 Then use the async capability of readline so that you have a select loop from which you can call functions. 然后使用readline的异步功能,以便您有一个select循环,您可以从中调用函数。

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 . 首先,Python readline库不支持异步readline函数调用,但是使用ctypes将Python直接连接到readline很容易

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. time.sleep可以处理小数秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM