当前位置: 首页 > 知识库问答 >
问题:

如何终止/中断/中止Python控制台/sys。stdin readline()?

左丘繁
2023-03-14

在线程中,我有一个从用户控制台读取输入的循环。主线程正忙于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

主thead调用startGUI(),其中包含一个tk。mainloop()调用。当我按下窗口上的X关闭按钮(这是Linux)时,Tkinter关闭窗口,mainloop()返回。然后我试着关闭stdin,希望这个系统。stdin将关闭并导致系统故障。斯丁。readline()将以一个很好的EOF终止,允许我的stdinLoop线程终止。

# 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")

系统。斯丁。realine()永远不会在sys之后返回。斯丁。close()。(stdinTh.join()用于同步关闭。)

我认为Python readline()做了一些聪明的事情(在一种叫做NetCommand的东西中),当stdin关闭时,它不会干净地返回。

Python是否认为同时拥有Tkinter GUI和交互式使用stdin是邪恶的?

我试着用sys。斯丁。读(1),但它似乎是一个缓冲区,并返回整行——而不是像我认为读(1)会读取一个字节/字符。

共有1个答案

汪高岑
2023-03-14

用daemon=True启动stdin读取线程。当主线程终止时,它将自动终止。您不需要显式地使用stdin做任何事情。(您也没有机会在stdin阅读线程中进行清理。)例如:

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

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

stdin上的read()stdin关闭时不会返回。我不知道你为什么期待它。这不是特定于Python的行为。至少在我的Linux/glibc系统上,同样的情况也发生在C中。

您可以通过向被阻止的线程发送一个信号(例如SIGUSR1)来打破阻塞read()。在C语言中,可以使用pthread\u kill()来实现这一点。Python没有提供一种简单的方法来实现这一点,这是有充分理由的;但是如果你坚持,你可以用ctypes来做。

但更干净/更安全的方法是使用select。选择从stdin或线程间通信管道读取,以先可用的为准:

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,在Windows中,您无法在sys上选择()。stdin

 类似资料:
  • 我是Apache Kafka的新手,我正在尝试从一个主题中获取信息。我从控制台运行以下命令来查看消息: 但在那之后,我可以看到一个名为“控制台-消费者-4158”的消费者被创建,我不小心关闭了控制台。 如何终止正在运行的消费者?

  • 我试图用< code>exec()调用PHP CLI脚本中的一个长期运行的shell命令。但是我无论如何也想不出如何中断PHP脚本并杀死产生的子进程。好像我一调用< code>exec(),我的信号处理程序就被忽略了。下面的代码像我预期的那样工作;如果我向进程发送SIGTERM,它会回显< code>SIGTERM并立即退出。 但是,如果我替换< code > sleep(60);与< code

  • 我已经使用Quartz Scheduler安排一个作业在每个月的最后一天执行。现在Quartz正在tomcat控制台中记录大量DEBUG信息。我已经成功关闭了使用log4j属性的日志记录。但是现在由于某种原因,我必须使用log4j2,现在我必须在log4j2.xml文件中做同样的事情。有人能告诉我如何设置log4j2 xml配置来停止石英调度程序日志记录吗? 谢谢,苏罗迪普

  • 控制台-频道-停止 接口URL {youke-url}/console/Index.php?c=live&a=stop&timestamp=1607677497&access_key=abc&sign=04394c5a45b6920bed314e94e178ebcf1dfded74 请求方式 POST Content-Type form-data 请求Query参数 参数 示例值 是否必填 参数描

  • 我写了一个程序在IDLE令牌化文本文件,它开始令牌349文本文件!我怎样才能阻止它?如何停止正在运行的Python程序?

  • 问题内容: 我用IDLE编写了一个程序来标记文本文件,然后开始标记349个文本文件!我该如何阻止它?如何停止正在运行的Python程序? 问题答案: 要停止程序,只需按 + 。