【问题标题】:Python (2.7) raw_input does not response user input when another thread is running当另一个线程正在运行时,Python (2.7) raw_input 不响应用户输入
【发布时间】:2018-05-01 18:40:36
【问题描述】:

我有一个小型 python 服务器来执行以下工作:

  • 主线程正在使用 raw_input 获取用户输入;
  • 另一个线程(即后台线程)由主线程启动,以执行与用户输入对应的作业。作业都是用 bash 脚本编写的,所以这个线程使用 subprocess.Popen 来运行脚本。

高级代码是这样的(只是抽象一下,因为详细的代码太长,这里就不复制了……):

# A global queue is initialized to cache user inputs
command_queue = Queue.Queue()

# This is the background-thread running bash script based on user's input
class command_runner(Thread):

  def run(self):
    user_command = command_queue.get()
    # code to run bash script specified in user_command, using Popen

class main_program(object):

  def listen_user_input(self):
    command_runner.start()
    while True:
      user_input = raw_input("Please input command:")
      command_queue.put(user_input)

我注意到当后台线程 (command_runner) 运行一些 bash 脚本时,主程序的 raw_input 有时不响应任何用户输入。 raw_input 好像卡住了。

其他一些可能有用的信息:

  • command_running 运行的 bash 脚本是长时间运行但不是繁重的脚本(通常约 10 分钟)。所以当 raw_input 卡住时,机器并没有耗尽资源。
  • 某些脚本可能会使用“ssh -q some_command 2>&1”通过 ssh 连接到其他机器(因此 ssh 命令会安静运行)。
  • bash 脚本的所有 stdout 和 stderr 都通过“Popen(user_command, stderr=sys.stdout.fileno(), stdout=log_fp)”重定向到一个文件

【问题讨论】:

  • 如果您将stdin=subprocess.PIPE 添加到Popen,此错误是否仍然存在?想知道子进程是否继承了 Python 的 stdin 并从 raw_input 窃取它
  • @scnerd 似乎您的解决方案有效!你能解释一下吗(也许只是回复,所以我会接受你的回答~)非常感谢!

标签: raw-input


【解决方案1】:

尝试将stdin=subprocess.PIPE 添加到您的Popen 通话中:

Popen(..., stdin=subprocess.PIPE, ...)

默认为Popen inherits its parent's file descriptors,包括stdin。你明确地给它一个新的stdoutstderr,但不是一个新的stdin,因此它是从你的主要 Python 进程继承的。我的猜测是stdin 被子进程捕获(即使该进程不需要它),从而阻止您对raw_input 的调用接收输入并返回,直到Popen 进程完成并返回控制权stdin.

如果进程可能会尝试从 stdin 读取数据,而您不打算向该管道写入任何内容,您也可以使用以下方式从 /dev/null(在 linux 上)中读取数据:

Popen(..., stdin=open('/dev/null', 'rb').fileno(), ...)

这将允许它(无法)从标准输入读取而不挂起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多