我如何与控制台应用程序交互,就像我是在其中输入内容的用户一样? [英] How do I interact with a console app as if I'm a user typing things into it?

查看:115
本文介绍了我如何与控制台应用程序交互,就像我是在其中输入内容的用户一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  * * * STARTREK * * * 

按返回继续。

多长时间游戏:短
多技能游戏:公平
输入密码:hunter2
10 Klingons
2 starbases at 3,6,0, 2
杀死Klingon

命令需要400个单位:

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

 >>>导入子流程
>> t = subprocess.Popen('trek',stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.STDOUT)

不幸的是:

 >> t.communicate(’’)
(’,无)
>>> t.poll()
-2
>> t.communicate(’’)
追溯(最近一次通话最近):
文件< stdin>,在< module>中的第1行
文件 /usr/lib/python2.7/subprocess.py,第754行,在通信中
返回self._communicate(输入)
文件 /usr/lib/python2.7 /subprocess.py,第1297行,在_communicate
self.stdin.flush()
ValueError:已关闭文件


它随我 .communicate()一起结束。它似乎响应了我的第一个 .communicate()

 > ;>> t = subprocess.Popen( trek,stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.STDOUT)
>> t.communicate('\n')
('\n * * * STARTREK * * * \n\n按回车键继续.\n游戏长度为',无)

但是我需要能够读取stdout才能弄清楚下一个stdin应该是什么。因此,如何在不执行任何操作的情况下将东西发送到stdin,即不告诉Trek输入的结尾呢?



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

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

这会永远挂下去:

  ^ CTraceback(最近一次通话最近):
文件< stdin>,在< module>中的第1行。
KeyboardInterrupt
>> t.stdout.readline()
''

那么现在是怎么回事?

解决方案

假设这是Linux,请使用 pexpect 模块。它是为处理交互式程序而编写的。诸如communication()之类的技术不起作用,因为它们等待程序退出。简单读取无法正常工作,因为该程序尚未刷新其粗壮状态,因此没有任何内容可读取。您可以创建自己的pty并在调用Popen()时使用它,或让pexpect为您完成工作。


I'm trying to write a Python program that interacts with the bsdgames trek program. It's kind of like 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: 

I'm currently trying to use subprocess.Popen() to interact with it:

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

Unfortunately:

>>> 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

It ends itself as soon as I .communicate() with it. It seems to respond to my first .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)

But I need to be able to read stdout to be able to figure out what the next stdin should be. So how do I send stuff to stdin without doing whatever is telling trek that that's the end of its input?

EDIT: Someone suggested t.stdin.write(). This works, but now I can't find a way to read the results:

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

This hangs forever so:

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

So now what's going on?

解决方案

Assuming this is linux, Use the pexpect module. It's written to deal with interactive programs. Techniques like communicate() don't work because they wait for the program to exit. Simply reading doesn't work because the program hasn't flushed its stout so there is nothing to read. You can create your own pty and use that when calling Popen() or let pexpect do the work for you.

这篇关于我如何与控制台应用程序交互,就像我是在其中输入内容的用户一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆