2013-03-04 209 views
2

我正在为Python命令行应用程序编写测试框架。应用程序将创建目录,在当前目录中调用其他shell脚本,并在Stdout上输出。使用python子进程模块,如命令行模拟器

我试图将{Python-SubProcess,CommandLine}组合等同于{Selenium,Browser}。第一个组件播放东西在第二个和检查如果输出是预期的。我面临以下问题

  1. Popen构造会在该命令完成后接受一个命令并返回。我想要的是对进程进行实时处理,以便我可以运行进一步的命令+验证,并最终关闭一次完成的shell
  2. 为编写一些基础结构代码以实现此目的,我很好,因为我们有很多命令行应用程序需要像这样测试。

这里是我运行

p = subprocess.Popen("/bin/bash", cwd = test_dir) 
p.communicate(input = "hostname") --> I expect the hostname to be printed out 
p.communicate(input = "time") --> I expect current time to be printed out 

样本代码,但该过程将挂起或可能是我做错了什么。另外我该如何“抓住”该子过程的输出,以便我可以断言存在某种东西?

+1

无法为单个进程调用通信()两次。我已经更新了答案。 – Ellioh 2013-03-04 16:31:31

+0

沟通('主机名\ ntime \ nexit \ n')可能吗?你真的需要交互式地处理这个过程,还是只执行多个命令?后者更容易。 – Ellioh 2013-03-04 16:56:23

回答

2

subprocess.Popen允许您在启动进程后继续执行。 Popen对象暴露wait(),poll()和许多其他方法与运行时的子进程进行通信。这不是你需要的吗?

请参阅Popen constructorPopen对象描述的详细信息。

这里是运行击在Unix系统并执行命令的一个小例子:

from subprocess import Popen, PIPE 
p = Popen (['/bin/sh'], stdout=PIPE, stderr=PIPE, stdin=PIPE) 
sout, serr = p.communicate('ls\n') 
print 'OUT:' 
print sout 
print 'ERR:' 
print serr 

UPD:communicate()等待进程终止。如果你不需要,你可以直接使用适当的管道,尽管这通常会给你带来相当难看的代码。

UPD2:您更新了问题。是的,您无法在单个流程中拨打communicate两次。您可以将所有需要在一次调用中执行的命令发送至communicate,并检查整个输出或使用管道(Popen.stdin,Popen.stdout,Popen.stderr)。如果可能,我强烈建议使用第一种解决方案(使用communicate)。

否则,您将不得不放置一个命令来输入并等待一段时间以获得所需的输出。你需要的是非阻塞阅读,以避免在没有任何可读的情况下挂起。 Here是一个配方,如何使用线程模拟管道上的非阻塞模式。代码很丑陋,而且很奇怪,这样一个简单的目的很复杂,但这就是它的完成方式。

另一种选择可能是使用p.stdout.fileno()调用select.select(),但这种方式在Windows上不起作用(在Windows上,select仅对源自WinSock的对象进行操作)。如果你不在Windows上,你可以考虑它。

+0

我看到我错过了stdin = PIPE。让我试试看 – 2013-03-04 16:23:09

+1

是的,stdin = PIPE是必不可少的。认为这是问题。 – Ellioh 2013-03-04 16:23:47

+0

那么如何运行两个如上所述的通信调用?上述程序挂起? (我的例子中有一个) – 2013-03-04 16:31:48

1

而不是使用纯subprocess的你可能会发现Python的SH库非常有用:

http://amoffat.github.com/sh/

下面是一个例子,如何在异步交互循环与SH建:

http://amoffat.github.com/sh/tutorials/2-interacting_with_processes.html

解决此问题的另一个(旧)库是pexpect:

http://www.noah.org/wiki/pexpect

+0

或者只是使用'code'模块。 – 2013-03-04 18:42:16

+0

据我所知,sh和pexpect是POSIX-only库。 – Ellioh 2013-03-05 11:18:29

+0

我以为整个命令行的东西只是POSIX;) – 2013-03-05 16:26:13

相关问题