Rib*_*ibo 3 python multithreading tkinter python-2.7
在线程中,我有一个循环从用户控制台读取输入。主线程忙于Tkinter mainloop()。如何终止该程序?
Run Code Online (Sandbox Code Playgroud)while True: ln = sys.stdin.readline() try: ln = ln[:-1] # Remove LF from line if len(ln)==0: continue # Ignore blank lines ...and so on主主题调用包含tk.mainloop()调用的startGUI()。当我按下窗口(这是Linux)上的X关闭按钮时,Tkinter关闭窗口,并且mainloop()返回。然后,我尝试关闭stdin,希望sys.stdin将关闭并导致sys.stdin.readline()将以一个不错的EOF终止,从而允许我的stdinLoop线程终止。
Run Code Online (Sandbox Code Playgroud)# Start up the GUI window startGUI() # Doesn't return until GUI window is closed, tk.mainloop is called here # # Wait for stdinLoop thread to finish sys.stdin.close() # Hopefully cause stdinTh to close print("waiting for stdinTh to join") stdinTh.join() print("joined stdinTh")
sys.stdin.realine()永远不会在sys.stdin.close()之后返回。(stdinTh.join()用于同步关闭。)
我认为Python readline()做的聪明的事情(在NetCommand中)在关闭stdin时不会干净地返回。
Python认为同时拥有Tkinter GUI和交互使用stdin 是否有害?
我尝试使用sys.stdin.read(1),但是似乎缓冲了一行并返回了整行-而不是像我认为的read(1)那样读取一个字节/字符。
使用来启动stdin-reading线程daemon=True。当主线程终止时,它将自动终止。您不需要显式地使用stdin进行任何操作。(您也没有机会在stdin读取线程中进行清理。)例如:
Run Code Online (Sandbox Code Playgroud)stdinTh = threading.Thread(target=stdinLoop, name="stdinTh") stdinTh.daemon = True stdinTh.start()
sys.stdin.readline()最终归结为阻塞的read()系统调用。
read()关闭stdin时on 不返回stdin。我不确定为什么会这样。这不是特定于Python的行为。至少在我的Linux / glibc系统上,在C中也是如此。
您可以read()通过向SIGUSR1被阻止的线程发送信号(例如)来突破阻塞。在C语言中,您可以使用pthread_kill()它。Python并没有提供简便的方法来执行此操作,这是有充分理由的。但是如果您坚持使用,可以使用ctypes。
但一个更清洁/更安全的方法是使用select.select从读取或者标准输入或线程间通信管道,取其可用第一:
import os, select, sys, threading, time
def printer_loop(quit_pipe):
    while True:
        sys.stdout.write("Say something: ")
        sys.stdout.flush()
        (readable, _, _) = select.select([sys.stdin, quit_pipe], [], [])
        if quit_pipe in readable:
            print("Our time is up!")
            break
        # This is not exactly right, because `sys.stdin` could become
        # ready for reading before there's a newline on there, so
        # `readline` could still block. Ideally you would do some
        # custom buffering here.
        line = sys.stdin.readline()
        print("You said: '%s' - well said!" % line.strip())
def main():
    print("Starting thread...")
    (pipe_read, pipe_write) = os.pipe()
    thread = threading.Thread(target=printer_loop, args=(pipe_read,))
    thread.start()
    time.sleep(5)
    print("Interrupting thread...")
    os.write(pipe_write, b'.')
    print("Joining thread...")
    thread.join()
    print("All done!...")
if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)
这不能移植到Windows上,而您不能select()在Windows上移植sys.stdin。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           755 次  |  
        
|   最近记录:  |