像命令行模拟器一样使用 python 子进程模块 [英] Use python subprocess module like a command line simulator

查看:26
本文介绍了像命令行模拟器一样使用 python 子进程模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a test framework in Python for a command line application. The application will create directories, call other shell scripts in the current directory and will output on the Stdout.

我试图将 {Python-SubProcess, CommandLine} 组合视为等同于 {Selenium, Browser}.第一个组件播放第二个组件,检查输出是否符合预期.我面临以下问题

I am trying to treat {Python-SubProcess, CommandLine} combo as equivalent to {Selenium, Browser}. The first component plays something on the second and checks if the output is expected. I am facing the following problems

  1. Popen 构造接受一个命令并在该命令完成后返回.我想要的是进程的实时句柄,以便我可以运行进一步的命令 + 验证,并在完成后最终关闭外壳
  2. 我可以编写一些基础设施代码来实现这一点,因为我们有很多命令行应用程序需要像这样进行测试.

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

Here is a sample code that I am running

 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 

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

but the process hangs or may be I am doing something wrong. Also how do I "grab" the output of that sub process so I can assert that something exists?

推荐答案

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

subprocess.Popen allows you to continue execution after starting a process. The Popen objects expose wait(), poll() and many other methods to communicate with a child process when it is running. Isn't it what you need?

参见 Popen 构造函数Popen 对象描述详情.

See Popen constructor and Popen objects description for details.

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

Here is a small example that runs Bash on Unix systems and executes a command:

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() 等待进程终止.如果你不需要它,你可以直接使用适当的管道,尽管这通常会给你带来相当丑陋的代码.

UPD: communicate() waits for process termination. If you do not need that, you may use the appropriate pipes directly, though that usually gives you rather ugly code.

UPD2:您更新了问题.是的,您不能为单个进程调用两次 communicate.您可以在一次调用 communicate 中提供您需要执行的所有命令并检查整个输出,或者使用管道(Popen.stdinPopen.标准输出Popen.stderr).如果可能,我强烈推荐第一种解决方案(使用 communicate).

UPD2: You updated the question. Yes, you cannot call communicate twice for a single process. You may either give all commands you need to execute in a single call to communicate and check the whole output, or work with pipes (Popen.stdin, Popen.stdout, Popen.stderr). If possible, I strongly recommend the first solution (using communicate).

否则,您将不得不输入命令并等待一段时间才能获得所需的输出.您需要的是非阻塞读取以避免在没有任何读取时挂起.这里是如何模拟非使用线程的管道阻塞模式.代码是丑陋的,而且为了这样一个微不足道的目的而奇怪地复杂,但它就是这样完成的.

Otherwise you will have to put a command to input and wait for some time for desired output. What you need is non-blocking read to avoid hanging when there is nothing to read. Here is a recipe how to emulate a non-blocking mode on pipes using threads. The code is ugly and strangely complicated for such a trivial purpose, but that's how it's done.

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

Another option could be using p.stdout.fileno() for select.select() call, but that won't work on Windows (on Windows select operates only on objects originating from WinSock). You may consider it if you are not on Windows.

这篇关于像命令行模拟器一样使用 python 子进程模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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