在 curses 中打印线程函数,Python

Print a threading function in curses, Python

在我的项目中,我必须在控制台上打印一些存储在数据库中的数据。我有两个 return 字符串的函数。我应该将这些数据打印成两列。 我想使用 python 中的模块 curses 来创建这两列。 到目前为止一切都很好。 另一件事是我的两个函数使用 threading.Timer。因此,生成的字符串每 10 秒更改一次,例如,如果我将 Timer 设置为 10。 因此,当我将函数的结果放在列的 addstr() 上时,它会正确打印第一个字符串,但即使我的字符串发生变化也不会发生任何变化。否则,当我调整控制台大小时,我注意到字符串发生了变化。 这是我的代码:

import sys,os
import curses , curses.panel 
import datetime
import time
import threading



def time_func():
    printStr = threading.Timer(10,time_func)
    printStr.start()
    s = "Simple example that display datetime \n" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 
    return s 

def draw_menu():


    k = 0
    cursor_x = 0
    cursor_y = 0


    # Clear and refresh the screen
    stdscr = curses.initscr()
    stdscr.clear()
    stdscr.refresh()

    # Initialize colors in curses
    curses.start_color()
    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
    curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
    curses.curs_set(0)
    # Loop where k is the last character pressed
    while (k != ord('q')):

        # Declaration of strings
        statusbarstr = "Press 'q' to exit | STATUS BAR "

        '''Draw borders of the different columns'''
        height, width = stdscr.getmaxyx()
        stdscr.border()
        stdscr.vline(1, 3 * height // 4, '|', width - 2)
        stdscr.vline(1, height // 4, '|', width - 2)
        stdscr.refresh()

        '''Initialize the Statistics column'''
        column_one = curses.newwin(height - 2, 3 * width // 4, 1,
                                           1)
        _, a_x = column_one.getmaxyx()
        column_one.attron(curses.color_pair(1))
        column_one.attron(curses.A_BOLD)
        column_one.addstr(0, a_x // 2 - 2, "column one")
        column_one.hline(1, 0, '-', a_x)
        column_one.attroff(curses.color_pair(1))
        column_one.attroff(curses.A_BOLD)

        # I want to add my string here for example : 
        line = time_func()
        column_one.addstr(3,1, line)


        column_one.noutrefresh()

        '''Initialize the Alerts column'''
        column_two = curses.newwin(height - 2, width // 4, 1,
                                       3 * width // 4 )
        _, s_x = column_two.getmaxyx()
        column_two.attron(curses.color_pair(1))
        column_two.attron(curses.A_BOLD)
        column_two.addstr(0, s_x // 2 - 5, "column two")
        column_two.hline(1, 0, '-', s_x)
        column_two.attroff(curses.color_pair(1))
        column_two.attroff(curses.A_BOLD)

        column_two.addstr(3, s_x // 2 - 5,"test")

        column_two.noutrefresh()



        # Render status bar
        stdscr.attron(curses.color_pair(3))
        stdscr.addstr(height-1, 0, statusbarstr)
        stdscr.addstr(height-1, len(statusbarstr), " " * (width - len(statusbarstr) - 1))
        stdscr.attroff(curses.color_pair(3))

        # Turning on attributes for title
        stdscr.attron(curses.color_pair(2))
        stdscr.attron(curses.A_BOLD)

        # Rendering title


        # Turning off attributes for title
        stdscr.attroff(curses.color_pair(2))
        stdscr.attroff(curses.A_BOLD)

        # Print rest of text

        stdscr.move(height - 2, width - 2)

        # Refresh the screen
        stdscr.refresh()
        # Wait for next input
        k = stdscr.getch()

def main():
    curses.wrapper(draw_menu())

if __name__ == "__main__":
    main()

curses 函数draw_menu 在循环结束时等待输入。如果您调整终端的大小,那

k = stdscr.getch()

returns a KEY_RESIZE,并再次运行循环。

您可以将其更改为等待一小段时间再放弃 getch。那会 return 一个 -1.

通常使用 timeout(在 curses 中)完成,例如 50 毫秒。有一个 wrapper for that in Python (and by the way its description is incorrect). You should read the ncurses manual page for timeout.

有时人们会说使用 nodelay,这通常是个糟糕的建议,因为它会使 draw_menu 线程使用大部分 CPU 时间。