gpt4 book ai didi

python - 你如何终止/中断/中止 Python 控制台/sys.stdin readline()?

转载 作者:行者123 更新时间:2023-12-01 15:37:55 29 4
gpt4 key购买 nike

在线程中,我有一个从用户控制台读取输入的循环。主线程正忙于 Tkinter mainloop()。我该如何终止这个程序?

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

The main thead calls startGUI() which contains a tk.mainloop() call. When I press the X close button on the window (this is Linux), Tkinter closes the window and mainloop() returns. I then try to close stdin hoping that sys.stdin will close and cause sys.stdin.readline() will terminate with a nice EOF allowing my stdinLoop thread terminate.

# 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 和交互使用标准输入是邪恶的

我尝试使用 sys.stdin.read(1),但似乎缓冲了一行并返回整行——而不是像我认为的 read(1) 那样读取一个字节/字符。

最佳答案

让线程成为守护线程,自动终止

daemon=True 启动标准输入读取线程.当主线程终止时,它将自动终止。你不需要明确地对标准输入做任何事情。 (您也没有机会在标准输入读取线程中进行清理。)例如:

stdinTh = threading.Thread(target=stdinLoop, name="stdinTh")
stdinTh.daemon = True
stdinTh.start()

如果你不能或不想使用守护线程

sys.stdin.readline() 最终归结为阻塞 read()系统调用。

stdin 关闭时, stdin 上的

read() 不返回。我不确定你为什么期望它。这不是特定于 Python 的行为。至少在我的 Linux/glibc 系统上,同样的情况发生在 C 中。

您可以通过向阻塞线程发送信号(例如SIGUSR1)来摆脱阻塞read()。在 C 中,您可以使用 pthread_kill()为了那个原因。 Python 没有提供一种简单的方法来做到这一点,这是有充分理由的;但如果你坚持,你可以do it with 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()

这不能移植到 Windows,您不能在 sys.stdinselect()

关于python - 你如何终止/中断/中止 Python 控制台/sys.stdin readline()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45515478/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com