Pexpect模块简介:
Pexpect 是 Don Libes 的 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块。 Pexpect 的使用范围很广,可以用来实现与 ssh、ftp 、telnet 等程序的自动交互;可以用来自动复制软件安装包并在不同机器自动安装;还可以用来实现软件测试中与命令行交互的自动化。
【Pexpect仅能在Unix/Linux平台下使用。】
Expect 程序主要用于人机对话的模拟,就是那种系统提问,人来回答 yes/no ,或者账号登录输入用户名和密码等等的情况。因为这种情况特别多而且繁琐,所以很多语言都有各种自己的实现。最初的第一个 Expect 是由 TCL 语言实现的,所以后来的 Expect 都大致参考了最初的用法和流程,
①整体来说大致的流程包括:
1.运行程序
2.程序要求人的判断和输入
3.Expect 通过关键字匹配
4.根据关键字向程序发送符合的字符串
pexpect 是 Python 语言的类 Expect 实现。从我的角度来看,它在功能上与 TCL 语言的实现还是有一些差距,比如没有buffer_full 事件、比如没有 expect before/after 事件等,但用来做一般的应用还是足够了。
②基本使用流程
pexpect 的使用说来说去,就是围绕3个关键命令做操作:
1.首先用 spawn 来执行一个程序
2.然后用 expect 来等待指定的关键字,这个关键字是被执行的程序打印到标准输出上面的
3.最后当发现这个关键字以后,根据关键字用 send 方法来发送字符串给这个程序
第一步只需要做一次,但在程序中会不停的循环第二、三步来一步一步的完成整个工作。掌握这个概念之后 pexpect 的使用就很容易了。当然 pexpect 不会只有这 3 个方法,实际上还有很多外围的其他方法,我们一个一个来说明
③句柄
1.是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。
2.整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的实例,
④匹配一系列输出
通过 pexpect.spawn() 可以创建一个进程,并通过操作这个进程的句柄来控制程序。
process = pexpect.spawn("ftp sw-tftp", logfile=sys.stdout)
实际上, expect() 可以匹配一系列输出,通过检查匹配到的输出,我们可以做不同的事情。比如之前 spawn 的 ftp 连接,如果我们输入用户名之后有不同的情况,就可以通过监控这些不同情况来做不同的动作,比如:
index = process.expect([
'Permission Denied',
'Terminal type',
'ftp>',
])
if index == 0:
print "Permission denied at host, can't login."
process.kill(0)
elif index == 1:
print "Login ok, set up terminal type…"
process.sendline('vty100')
process.expect("ftp>")
elif index == 2:
print "Login Ok, please send your command"
process.interact()
1.pexpect.EOF - 匹配终止信号
EOF 变量使用范围很广泛,比如检查 ssh/ftp/telnet 连接是否终止啊,文件是否已经到达末尾啊。 pexpect 大部分脚本的最后都会检查 EOF 变量来判断是不是正常终止和退出,比如下面的代码:
process.expect("ftp>")
process.sendline("by")
process.expect(pexpect.EOF)
print "ftp connect terminated."
2.pexpect.TIMEOUT - 匹配超时信号
TIMEOUT 变量用来匹配超时的情况,默认情况下 expect 的超时时间是 60 秒,如果超过 60 秒还没有发现期待的关键字,就会触发这个行为,比如:
匹配pexpect.TIMEOUT的动作,只有超时事件发生的时候才会有效
index = process.expect(['ftp>', pexpect.TIMEOUT],)
if index == 1:
process.interactive() ; # 将控制权交给用户
elif index == 2:
print "Time is out."
process.kill(0) ; # 杀掉进程
那么怎么改变超时时间呢?其实可以修改spawn对象里的timeout参数:
下面的例子仅仅加了一行,这样就改变了超时的时间了
process.timeout = 300 ; # 注意这一行
index = process.expect(['ftp>', pexpect.TIMEOUT],)
if index == 1:
process.interactive() ; # 将控制权交给用户
elif index == 2:
print "Time is out."
process.kill(0) ; # 杀掉进程