Python (2.7) 当另一个线程 运行 时 raw_input 不响应用户输入
Python (2.7) raw_input does not response user input when another thread is running
我有一个小型 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) 运行ning 一些 bash 脚本时,主程序的 raw_input 有时不响应任何用户输入。 raw_input 似乎卡住了。
其他一些可能有用的信息:
- command_running 的 bash 脚本 运行 很长 运行 但不是很重的脚本(通常约 10 分钟)。因此,当 raw_input 卡住时,机器不会 运行 耗尽资源。
- 一些脚本可能会使用 "ssh -q some_command 2>&1" ssh 到其他机器(所以 ssh 命令是 运行ning 悄悄地)。
- bash脚本的所有stdout和stderr都通过"Popen(user_command, stderr=sys.stdout.fileno(), stdout=log_fp)"
重定向到一个文件
尝试将 stdin=subprocess.PIPE
添加到您的 Popen
调用中:
Popen(..., stdin=subprocess.PIPE, ...)
默认情况下,Popen
inherits its parent's file descriptors,包括stdin
。你明确地给它一个新的 stdout
和 stderr
,而不是一个新的 stdin
,因此它继承了你的主要 Python 进程。我的猜测是 stdin
被子进程捕获(即使该进程不需要它),阻止您对 raw_input
的调用接收输入并返回,直到 Popen
流程结束,returns 控制 stdin
。
如果进程可能会尝试从 stdin
读取数据,而您不打算向该管道写入任何内容,您也可以让它从 /dev/null
(在 linux ), 使用类似:
Popen(..., stdin=open('/dev/null', 'rb').fileno(), ...)
这将允许它(无法)从 stdin 读取而不挂起。
我有一个小型 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) 运行ning 一些 bash 脚本时,主程序的 raw_input 有时不响应任何用户输入。 raw_input 似乎卡住了。
其他一些可能有用的信息:
- command_running 的 bash 脚本 运行 很长 运行 但不是很重的脚本(通常约 10 分钟)。因此,当 raw_input 卡住时,机器不会 运行 耗尽资源。
- 一些脚本可能会使用 "ssh -q some_command 2>&1" ssh 到其他机器(所以 ssh 命令是 运行ning 悄悄地)。
- bash脚本的所有stdout和stderr都通过"Popen(user_command, stderr=sys.stdout.fileno(), stdout=log_fp)" 重定向到一个文件
尝试将 stdin=subprocess.PIPE
添加到您的 Popen
调用中:
Popen(..., stdin=subprocess.PIPE, ...)
默认情况下,Popen
inherits its parent's file descriptors,包括stdin
。你明确地给它一个新的 stdout
和 stderr
,而不是一个新的 stdin
,因此它继承了你的主要 Python 进程。我的猜测是 stdin
被子进程捕获(即使该进程不需要它),阻止您对 raw_input
的调用接收输入并返回,直到 Popen
流程结束,returns 控制 stdin
。
如果进程可能会尝试从 stdin
读取数据,而您不打算向该管道写入任何内容,您也可以让它从 /dev/null
(在 linux ), 使用类似:
Popen(..., stdin=open('/dev/null', 'rb').fileno(), ...)
这将允许它(无法)从 stdin 读取而不挂起。