像命令行模拟器一样使用python子进程模块

我正在用Python为命令行应用程序编写测试框架.该应用程序将创建目录,在当前目录中调用其他shell脚本,并将在Stdout上输出.

我正在尝试将{Python-SubProcess,CommandLine}组合等同于{Selenium,Browser}.第一个组件在第二个组件上起作用,并检查是否期望输出.我面临以下问题

> Popen构造接受一条命令,并在该命令完成后返回.我想要的是该过程的实时处理程序,因此我可以运行进一步的命令验证,并在完成后最终关闭外壳
>我可以编写一些基础结构代码来实现此目的,因为我们有许多需要进行此类测试的命令行应用程序.

这是我正在运行的示例代码

 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 

但过程挂起,或者可能是我做错了.另外,我如何“抓取”该子过程的输出,以便可以断言某些东西存在?

解决方法:

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

有关详细信息,请参见Popen constructor和Popen对象描述.

这是一个在Unix系统上运行Bash并执行命令的小示例:

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:communication()等待进程终止.如果您不需要这样做,则可以直接使用适当的管道,尽管这样做通常会使您看起来很丑陋.

UPD2:您更新了问题.是的,您不能为一个进程调用两次通话.您可以在一次调用中提供执行所有命令以进行通信并检查整个输出,也可以使用管道(Popen.stdin,Popen.stdout,Popen.stderr).如果可能的话,我强烈建议第一个解决方案(使用通讯).

否则,您将必须输入命令并等待一段时间才能获得所需的输出.您需要的是非阻塞读取,以避免在没有读取内容时挂起. Here是如何使用线程在管道上模拟非阻塞模式的方法.出于如此琐碎的目的,代码很丑陋,而且很奇怪,但这就是它的完成方式.

另一个选择是使用p.stdout.fileno()进行select.select()调用,但这在Windows上不起作用(在Windows上,select仅对源自WinSock的对象起作用).如果您不在Windows上,则可以考虑使用.

上一篇:Python的subprocess.call和subprocess.run之间有什么区别


下一篇:如何在python中运行多行bash命令?