Планирование вызовов функций в пользовательском интерфейсе Python curses - PullRequest
1 голос
/ 14 февраля 2012

Я пытаюсь написать программу, которая будет иметь интерфейс 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 ]

4 голосов
/ 14 февраля 2012

В вашем скрипте две проблемы.

  1. Эта строка:

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

    повысит TypeError, поскольку addstr ожидает str, а не datetime, поэтому вам нужно заменить эту строку на что-то вроде:

    screen.addstr(12, 12, time.strftime("%a, %d %b %Y %H:%M"))
    
  2. Вторая проблема заключается в том, что рекурсивный вызов вызовов:

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

    Я никогда не использовал модуль sched, но немного расширил свои знания, и кажется, что .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()
0 голосов
/ 15 февраля 2012

Я думаю, что лучший способ решить эту проблему - использовать GNU readline для ввода, а не ввод проклятий по умолчанию. Затем используйте асинхронную возможность readline, чтобы у вас был цикл select, из которого можно вызывать функции.

Прежде всего, библиотека Python readline не поддерживает асинхронные вызовы функций readline, однако легко подключить Python напрямую к readline, используя ctypes.

Таким образом, у вас есть цикл выбора, который всегда находится под контролем. Когда нет ввода, проверьте часы, чтобы узнать, пора ли запустить вашу функцию. Если нет, поспите несколько миллисекунд, проверьте нажатие клавиши, посмотрите на часы и снова спите. time.sleep может обрабатывать доли секунды.

...