Как я могу обновить значение строки, не меняя ее положения, с помощью задания потока? [Python] - PullRequest
7 голосов
/ 05 августа 2020

У меня будет две работы в моем сценарии. После запуска задания другое будет запускать asyn c. Я использовал для этого Thread. И этот поток вернет некоторую информацию, в то время как другие будут считать эту информацию.

Я хочу сделать, чтобы при изменении значения счетчика поток также продолжал работать.

Показать, что я хочу:

-----------------------------------------
Count: 5
-----------------------------------------
thread keeps running...
thread keeps running...
thread keeps running...

На самом деле я добиваюсь этой цели, используя модуль curses, но это не совсем то, что я хотел. Потому что, когда я нажимаю ^C, содержимое терминала исчезает. Я хочу, чтобы они застыли на экране.

Код с проклятиями:

import sys
import time
import queue
import signal
import curses
import threading


def ctrl_c_handler(*args):
    sys.exit(0)


signal.signal(signal.SIGINT, ctrl_c_handler)

MESSAGE = "thread keeps running..."


def print_func(message):
    return message


def new_window(stdscr):
    que = queue.Queue()

    curses.curs_set(False)

    y, x = stdscr.getmaxyx()

    draw = x * "-"

    i = 3
    count = 1
    while True:
        thread = threading.Thread(target=lambda q, arg1: q.put(print_func(arg1)), args=(que, MESSAGE,), daemon=True)
        thread.start()
        result = que.get()

        try:
            stdscr.addstr(0, 0, draw)
            stdscr.addstr(1, 0, f"Count: {str(count)}")
            stdscr.addstr(2, 0, draw)
            stdscr.addstr(i, 0, result)

        except curses.error:
            pass

        stdscr.refresh()
        time.sleep(0.1)

        i += 1
        count += 1

        if i == y:
            stdscr.clear()
            i = 3


curses.wrapper(new_window)

Есть ли способ достичь той же цели без использования проклятий или проклятий без потери содержимого?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 08 августа 2020

Попробуйте следующее:

import sys
import time
import queue
import signal
import curses
import threading


ctrl_c_pressed_event = threading.Event()

def ctrl_c_handler(*args):
    ctrl_c_pressed_event.set()


signal.signal(signal.SIGINT, ctrl_c_handler)

MESSAGE = "thread keeps running..."


def print_func(message):
    return message


def new_window(stdscr):
    que = queue.Queue()

    curses.curs_set(False)

    y, x = stdscr.getmaxyx()

    draw = x * "-"

    i = 3
    count = 1
    while True:
        if ctrl_c_pressed_event.isSet():
            stdscr.getkey()
            break
        thread = threading.Thread(target=lambda q, arg1: q.put(print_func(arg1)), args=(que, MESSAGE,), daemon=True)
        thread.start()
        result = que.get()
        try:
            stdscr.addstr(0, 0, draw)
            stdscr.addstr(1, 0, f"Count: {str(count)}")
            stdscr.addstr(2, 0, draw)
            stdscr.addstr(i, 0, result)
        except curses.error:
            pass
        stdscr.refresh()
        time.sleep(0.1)
        i += 1
        count += 1
        if i == y:
            stdscr.clear()
            i = 3


curses.wrapper(new_window)
print('Program ended')

2 голосов
/ 08 августа 2020

Это делает curses.wrapper. измените функцию ctrl_c_handler следующим образом:

def ctrl_c_handler(*args):
    curses.nocbreak()
    scr.keypad(False)
    curses.echo()
    sys.exit(0)

и вместо использования функции wrapper запустите new_window следующим образом:

scr = curses.initscr()
new_window(scr)
...