【问题标题】:How do I interact with a console app as if I'm a user typing things into it?我如何与控制台应用程序交互,就好像我是用户在其中输入内容一样?
【发布时间】:2013-04-21 16:42:52
【问题描述】:

我正在尝试编写一个与 bsdgames trek 程序交互的 Python 程序。这有点像 Zork with Klingons:

   * * *   S T A R   T R E K   * * *

Press return to continue.

What length game: short
What skill game: fair
Enter a password: hunter2
10 Klingons
2 starbases at 3,6, 0,2
It takes 400 units to kill a Klingon

Command: 

我目前正在尝试使用subprocess.Popen() 与之交互:

>>> import subprocess
>>> t = subprocess.Popen('trek', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

不幸的是:

>>> t.communicate('')
('', None)
>>> t.poll()
-2
>>> t.communicate('')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 754, in communicate
    return self._communicate(input)
  File "/usr/lib/python2.7/subprocess.py", line 1297, in _communicate
    self.stdin.flush()
ValueError: I/O operation on closed file

只要我.communicate() 使用它,它就会自行结束。好像回复了我第一个.communicate()

>>> t = subprocess.Popen('trek', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>> t.communicate('\n')
('\n   * * *   S T A R   T R E K   * * *\n\nPress return to continue.\nWhat length game: ', None)

但我需要能够读取标准输出才能弄清楚下一个标准输入应该是什么。那么如何在不告诉 trek 输入结束的情况下将内容发送到标准输入?

编辑:有人建议t.stdin.write()。这可行,但现在我找不到读取结果的方法:

>>> t.stdin.write('\n')
>>> t.poll()
>>> t.stdout.read()

这会永远挂起:

^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>> t.stdout.readline()
''

那么现在发生了什么?

【问题讨论】:

标签: python command-line subprocess stdout stdin


【解决方案1】:

假设这是 linux,请使用 pexpect 模块。它是为处理交互式程序而编写的。诸如communicate() 之类的技术不起作用,因为它们等待程序退出。简单地阅读是行不通的,因为程序没有刷新它的粗壮,所以没有什么可阅读的。您可以创建自己的 pty 并在调用 Popen() 时使用它或让 pexpect 为您完成工作。

【讨论】:

    猜你喜欢
    • 2020-10-15
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多