(请参阅下面的编辑1进行更新)
我需要与我在Python 3中编写的菜单进行交互。
但是,无论我尝试什么,我都无法调用input()
行。
(这是get_action()
函数中的最后一行)。
以下是我想要与subprocess()
进行互动的(简化)脚本:
$ cat test_menu.py
#!/usr/bin/env python3
action_text = """
5. Perform addition
6. Perform subtraction
Q. Quit
"""
def get_action():
print(action_text)
reply = input("Which action to use? ")
if __name__ == "__main__":
get_action()
与subprocess()
进行交互的基于{p> test_menu.py
的代码是:
$ cat tests1.py
import subprocess
cmd = ["/usr/bin/python3","./test_menu.py"]
process = subprocess.Popen(cmd,
shell=False,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for i in range(8):
output = process.stdout.readline()
print output.strip()
process.stdin.write('%s\n' % "5")
process.stdin.flush()
但是,当我运行tests1.py,
时,它永远不会进入input()
行:
$ python ./tests1.py
5. Perform addition [default]
6. Perform subtraction
Q. Quit
有任何建议我如何让subprocess()
显示input()
行并与之互动(例如,显示Which action to use?
提示)?
修改1:
在@Serge建议之后,subprocess()
能够显示提示行,但它仍然不显示输入(5)我输入PIPE。
更改了tests1.py:
import subprocess
def terminated_read(fd, terminators):
buf = []
while True:
r = fd.read(1)
buf += r
if r in terminators:
break
return ''.join(buf)
cmd = ["/usr/bin/python3","./test_menu.py"]
process = subprocess.Popen(cmd,
shell=False,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for i in range(5):
output = process.stdout.readline()
print output.strip()
process.stdin.write("5\n")
process.stdin.flush()
for i in range(80):
output = terminated_read(process.stdout, "?")
print output," ",
执行:
$ python ./tests1.py
5. Perform addition [default]
6. Perform subtraction
Q. Quit
Which action to use?
答案 0 :(得分:1)
问题是readline
会在找到换行符之前读取一个流,而input("Which action to use? ")
不会打印一个换行符。
一个简单的解决方法是编写
...
reply = input("Which action to use? \n")
...
如果您不想(或不能)更改测试菜单中的任何内容,则必须实现超时读取,或者一次读取一个字符,直到找到新行或?
例如,这应该有效:
...
def terminated_read(fd, terminators):
buf = []
while True:
r = fd.read(1).decode()
buf += r
if r in terminators:
break
return ''.join(buf)
process = subprocess.Popen(cmd,
shell=False,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for i in range(8):
output = terminated_read(process.stdout, "\n?")
print(output.strip())
...
将答案传递给子流程很简单。困难的部分是猜测什么时候回答。在这里,您知道您可以在?
输入结束后立即回答。我更改了test_menu.py,以确认它正确地获取命令:
#!/usr/bin/env python3
import sys
action_text = """
5. Perform addition
6. Perform subtraction
Q. Quit
"""
def get_action():
print(action_text)
reply = input("Which action to use? ")
print("Was asked ", reply) # display what was asked
if reply == '5':
print("subtract...")
if __name__ == "__main__":
get_action()
包装器test1.py
就是:
import subprocess
cmd = ["/usr/bin/python3","./test_menu.py"]
def terminated_read(fd, terminators):
buf = []
while True:
r = fd.read(1).decode()
# print(r)
buf.append(r)
if r in terminators:
break
return "".join(buf)
process = subprocess.Popen(cmd,
shell=False,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
while True:
output = terminated_read(process.stdout, "\n?")
print(output.strip())
if output[-1] == '?':
break
process.stdin.write(('%s\n' % "5").encode())
cr = process.wait()
end = process.stdout.read().decode()
print("Child result >" + end + "<")
print("Child code" + str(cr))
从Python 3.4或Python 2.7开始,输出符合预期:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
Child result > Was asked 5
subtract...
<
Child code0
答案 1 :(得分:0)
以下应该有效(主要区别在于当它遇到菜单结束时停止读取标准输出):
#!/usr/bin/env python
import subprocess
cmd = ['./test_menu.py']
p = subprocess.Popen(cmd, shell=False, bufsize=0
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
menu = ''
while True:
output = p.stdout.read(1)
if output:
menu += output
else:
break
if menu.endswith('#: '):
break
print(p.communicate(raw_input(menu))[0])
#!/usr/bin/env python
import sys
action_text = '''
5. Perform addition
6. Perform subtraction
Q. Quit
#: '''
sys.stdout.write(action_text); sys.stdout.flush()
inp = sys.stdin.read()
print(inp)
用法:
[ 12:52 me@yourbase ~/test ]$ ./test1.py
5. Perform addition
6. Perform subtraction
Q. Quit
#: 5
5
[ 12:52 me@yourbase ~/test ]$ ./test1.py
5. Perform addition
6. Perform subtraction
Q. Quit
#: 12345
12345
答案 2 :(得分:0)
不确定您的目标是什么,但以下内容将采取输入,您可以在get_action
中随意执行任何操作:
action_text = """5. Perform addition
6. Perform subtraction
Q. Quit"""
def get_action():
print(action_text)
inp = input("Which action to use?\n")
print(inp)
print("Now do whatever")
if __name__ == "__main__":
get_action()
import subprocess
cmd = ["/usr/bin/python3","./test_menu.py"]
process = subprocess.Popen(cmd,
shell=False,
bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for line in iter(process.stdout.readline, ""):
print(line)
if line.rstrip() == "Which action to use?":
r = raw_input()
process.stdin.write(r+"\n")
示例运行:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
6
6
Now do whatever
添加几个功能:
def add():
return 4+ 6
def sub():
return 4 - 6
def get_action():
print(action_text)
inp = input("Which action to use?\n")
if inp == "5":
print(add())
elif inp == "6":
print(sub())
else:
print("Goodbye")
if __name__ == "__main__":
get_action()
输出:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
6
-2
添加:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
5
10
其他任何事情:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
q
Goodbye
如果你想在不接受用户输入的情况下编写,请忘记r并只写入stdin:
for line in iter(process.stdout.readline, ""):
print(line)
if line.rstrip() == "Which action to use?":
process.stdin.write("5\n")
输出继电器:
5. Perform addition
6. Perform subtraction
Q. Quit
Which action to use?
10