【问题标题】:Python curses, threading: Output thread reports a lagging value for global variablePython 诅咒,线程:输出线程报告全局变量的滞后值
【发布时间】:2018-01-10 04:40:41
【问题描述】:

我从一个带有 curses 的 python 程序开始,然后我实现了线程,它接受输入(这里是 A 和 D 按钮)并相应地更改 x。然后主块不断地在屏幕上显示 x 的值。但是,x(全局共享变量)的值是不同的。特别是,主块测量的 x 值总是落后于 inputThread 的值,但 inputThread 是完全响应的。是什么赋予了?如何让主块读取 inputThread 测量的 x 的真实值?

import time
import curses
import threading
from curses import wrapper
from time import sleep

def inputThread(stdscr):
    global x
    x = 0
    while True:
        c = stdscr.getch()
        curses.flushinp()
        if c == ord('a'):
            x -= 1
        elif c == ord('d'):
            x += 1
        stdscr.addstr("inputThread:" + str(x) + "\n" + "c:" + str(c))

def main(stdscr):
    curses.initscr()
    stdscr.clear()

    t = threading.Thread(target=inputThread, args=(stdscr,))
    t.setDaemon(True)
    t.start()

    while True:

        stdscr.clear()
        stdscr.addstr("\ndisplay window:" + str(x) + "\n")
        time.sleep(0.05)

wrapper(main)

样本输出;在下一次按键时,无论是 A 还是 D,显示窗口都会报告 9。

【问题讨论】:

    标签: python multithreading python-curses


    【解决方案1】:

    首先,您的全局变量x 应该在所有函数之外声明,但您已在inputThread 函数中声明它。 global x 告诉它不是在函数范围内创建另一个变量,而是使用和更改全局变量 x 的值。因此,在其他函数之外使用 0 删除和初始化 x

    现在你的问题来了。假设当守护进程和主线程一起运行时,守护进程方法只是停留在c = stdscr.getch() 等待按键,而主线程中主函数内的while 循环什么都不做,只是用文本display window: 0 看不到,因为屏幕在0.05s 中变得清晰,表示 FPS 太快而看不到屏幕。
    现在,当您键入其中任何一个 a or d 键时,守护程序会更新全局变量 x 的值,但在主线程获取该值之前,它正在虚拟屏幕上打印为 InputThread:*c:*** 和在这种情况下,主线程只打印前一个值0。所以解决方法是在更新x 后让守护线程休眠一段时间,同时主线程内的循环将导致显示x 的新更新值。这可以通过以下方式完成:

    import time
    import curses
    import threading
    from curses import wrapper
    from time import sleep
    
    x = 0
    
    def inputThread(stdscr):
        global x
        while True:
            c = stdscr.getch()
            curses.flushinp()
            if c == ord('a'):
                x -= 1
            elif c == ord('d'):
                x += 1
            sleep(0.05)
            stdscr.addstr("inputThread:" + str(x) + "\n" + "c:" + str(c))
    
    def main(stdscr):
        curses.initscr()
        stdscr.clear()
    
        t = threading.Thread(name ='daemon', target=inputThread, args=(stdscr,))
        t.setDaemon(True)
        t.start()
    
        while True:
            stdscr.clear()
            stdscr.addstr("\ndisplay window:" + str(x) + "\n")
            sleep(0.05)
    
    wrapper(main)
    

    希望对你有帮助。

    【讨论】:

    • 我不太明白为什么会这样,但确实如此。你能再解释一下这是怎么回事吗?
    • @FarazMasroor 最后一段解释了这一切。如果这回答了您的问题,请接受此答案。
    • 我可以看到你解释了它,但我真的不明白你所说的为什么有效。如果输入线程更新 x,那么在主循环的下一个循环中,主线程会看到 x 的新值吗?那么为什么输入循环需要等待呢?
    • 想想守护线程和主线程的同步
    • 你有没有想过display window:*会被打印在底部?
    猜你喜欢
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多