简单介绍
pexpect是 Don Libes 的 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块。它可以用来实现与ssh, ftp, telnet等程序的自动交互,参考官方文档:https://pexpect.readthedocs.io/en/stable/

安装均可以使用pip进行

注意:windows和linux安装模块是不同的。如下:
在linux下安装:pip3 install pexpect
在windows下安装: pip3.exe install winpexpect

在windows系统里创建子程序是:
import winpexpect
child = winpexpect.winspawn('command')
另:run(), pxssh()均不可使用

在linux系统里创建子程序是:
import pexpect
child = pexpect.spawn('cmd')

模块内主要的类/函数介绍

spawn / winspawn 类
作用:可以实现更复杂的交互,通过生成子程序进行sendline(发送命令)与expect(返回操作符)进行交互。
class spawn
def __init__(self, command, args=[], timeout=30, maxread=2000,
searchwindowsize=None, logfile=None, cwd=None, env=None,
username=None, domain=None, password=None)

个别参数解释:
timeout:交互等待的超时值,默认30秒
maxread:设置read buffer大小,
searchwindowsize:从输入缓冲区中进行模式匹配的位置,默认从开始匹配。
logfile:指定日志的记录位置

注意:pexpect不支持管道,重定向或通配符,如果需要使用,需要重新打开一个shell
简单用法:
# 第一步创建子程序,输入执行的操作命令,我这里是以telnet远程终端为例
child = pexpect.spawn('telnet ipaddress')
# 第二步从子命令返回的结果中进行匹配,语法:expect(pattern, timeout=-1),

pattern参数说明:可以为字符串,正则表达式,EOF,TIMEOUT,或者是以上类型的列表,若只提供字符串,匹配成功后返回0,若提供列表,匹配成功后返回列表的索引序号。未匹配成功,则会引发异常

timeout:为-1 使用默认的超时期限,设置为NONE,将阻塞至返回信息
child.expect('password:')
# 第三步匹配成功后,发送交互信息,这里发送密码
child.sendline(mypassword)

获取命令执行结果主要由3个基本属性。

child.before:输出匹配点之前的命令执行结果

child.after:输出匹配成功后的匹配点内容,如标识符:hostname#>

child.match:保存已匹配的匹配点对象,可以使用string,打印命令的执行结果。

pxssh类
是pexpect的派生类,用于建立ssh连接,比pexpect直接使用ssh时简单一些,内建3个方法:
login() 建立到目标机器的ssh连接;
logout() 释放该连接;
prompt() 等待提示符,通常用于等待命令执行结束。

pexpect.EOF 异常错误
获取pexpect错误信息,可能会有两种 EOF 异常被抛出,但是他们除了显示的信息不同,其实本质上是相同的。为了实用的目的,不需要区分它们,他们只是给了些关于你的 python 程序到底运行在哪个平台上的额外信息,这两个显示信息是:
End Of File (EOF) in read(). Exception style platform.
End Of File (EOF) in read(). Empty string style platform.
有些 UNIX 平台,当你读取一个处于 EOF 状态的文件描述符时,会抛出异常,其他 UNIX 平台,却只会静静地返回一个空字符串来表明该文件已经达到了状态。

pexpect.TIMEOUT异常错误
如果子程序没有在指定的时间内生成任何 output,那么 expect() 和 read() 都会产生 TIMEOUT 异常。超时默认是 30s,可以在 expect() 和 spawn 构造函数初始化时指定为其它时间
child.expect('password:', timeout=120) # 等待 120s
如果你想让 expect() 和 read() 忽略超时限制,即无限期阻塞住直到有 output 产生,设置 timeout 参数为 None。
代码如:
child = pexpect.spawn( "telnet 域名" )
child.expect( "login", timeout=None )

以上两个错误可以使用try语句来处理报错
try:
child=pexpect.spawn('telnet ip',timeout=5)
child.logfile = log
child.logfile_send=sys.stdout
child.expect("New password:")
child.sendline(mypassword)
child.expect("Retype new password:")
child.sendline(mypassword)
child.expect("passwd: all authentication tokens updated successfully.")
except pexpect.EOF:
pass
except pexpect.TIMEOUT:
pass

实例:自动登陆ftp

 import pexpect
# 即将 ftp 所要登录的远程主机的域名
ipAddress = '域名名称'
# 登录用户名
loginName = 'username'
# 用户名密码
loginPassword = 'password'
# 拼凑 ftp 将要执行的命令
cmd = 'ftp ' + ipAddress
# 利用 cmd 命令作为 spawn 类构造函数的参数,生成一个 spawn 类的对象
child = pexpect.spawn(cmd)
# 期望具有提示输入用户名的字符出现
index = child.expect(["(?i)name", "(?i)Unknown host", pexpect.EOF, pexpect.TIMEOUT])
# 匹配到了列表索引为0的字符串 "(?i)name",表明接下来要输入用户名
if index == 0:
# 发送登录用户名 + 换行符给子程序.
child.sendline(loginName)
# 期望 "(?i)password" 具有提示输入密码的字符出现.
index = child.expect(["(?i)password", pexpect.EOF, pexpect.TIMEOUT])
# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.
if (index != 0):
print "ftp login failed"
child.close(force=True)
# 匹配到了密码提示符,发送密码 + 换行符给子程序.
child.sendline(loginPassword)
# 期望登录成功后,提示符 "ftp>" 字符出现.
index = child.expect( ['ftp>', 'Login incorrect', 'Service not available',
pexpect.EOF, pexpect.TIMEOUT])
# 匹配到了 'ftp>',登录成功.
if (index == 0):
print 'Congratulations! ftp login correct!'
# 发送 'bin'+ 换行符给子程序,表示接下来使用二进制模式来传输文件.
child.sendline("bin")
print 'getting a file...'
# 向子程序发送下载文件 rmall 的命令.
child.sendline("get rmall")
# 期望下载成功后,出现 'Transfer complete.*ftp>',其实下载成功后,
# 会出现以下类似于以下的提示信息:
# 200 PORT command successful.
# 150 Opening data connection for rmall (548 bytes).
# 226 Transfer complete.
# 548 bytes received in 0.00019 seconds (2.8e+03 Kbytes/s)
# 所以直接用正则表达式 '.*' 将 'Transfer complete' 和提示符 'ftp>' 之间的字符全省去.
index = child.expect( ['Transfer complete.*ftp>', pexpect.EOF, pexpect.TIMEOUT] )
# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.
if (index != 0):
print "failed to get the file"
child.close(force=True)
# 匹配到了 'Transfer complete.*ftp>',表明下载文件成功,打印成功信息,并输入 'bye',结束 ftp session.
print 'successfully received the file'
child.sendline("bye")
# 用户名或密码不对,会先出现 'Login incorrect',然后仍会出现 'ftp>',但是 pexpect 是最小匹配,不是贪婪匹配,
# 所以如果用户名或密码不对,会匹配到 'Login incorrect',而不是 'ftp>',然后程序打印提示信息并退出.
elif (index == 1):
print "You entered an invalid login name or password. Program quits!"
child.close(force=True)
# 匹配到了 'Service not available',一般表明 421 Service not available, remote server has closed connection,程序打印提示信息并退出.
# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.
else:
print "ftp login failed! index = " + index
child.close(force=True)

实例:自动登陆交换机执行一条命令后退出,最好在linux系统下进行测试,在windows下使用winpexpect不好用

 #!/opt/python3/bin/python3
# _*_ coding:utf-8 _*_
# Author: Yong import pexpect
# 基本信息
ipAddr = '交换机IP'
pwd = '交换机登陆密码'
cmd = 'telnet ' + ipAddr # 连接设备,创建子进程
child = pexpect.spawn(cmd, timeout=300)
# 进行匹配返回标识符
index = child.expect(['Password:', pexpect.EOF, pexpect.TIMEOUT])
# 匹配到列表索引0的内容
if index == 0:
# 网络设备登陆直接提示密码,发送密码
child.sendline(pwd)
# 匹配返回标识符
index = child.expect('<A-3F-30>')
# 未匹配到标识符,退出
if index != 0:
exit('密码错误')
print('密码验证完成')
# 发送执行的命令
child.sendline('display version')
# 匹配返回的标识符
child.expect('<A-3F-30>')
# 打印命令执行结果
print(child.before)
# print('将telnet子程序执行权交给用户')
# child.interact() else:
# 匹配到EOF 或者TIMEOUT表示超过时间限制
print('telnet faild, EOF OR TIMEOUT',pexpect.EOF)
# 关闭连接
child.close()

python 终端模拟模块 pexpect的更多相关文章

  1. Python模块之pexpect

    一.pexpect模块介绍 Pexpect使Python成为控制其他应用程序的更好工具.可以理解为Linux下的expect的Python封装,通过pexpect我们可以实现对ssh,ftp,pass ...

  2. Python中的Pexpect模块的简单使用

    Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块. Pexpect 可以用来和像 ssh.ftp.passwd.telnet 等命令行程序进行自动交互.以下所有代码都是在K ...

  3. python终端颜色设置

    1.颜色定义说明 格式:\033[显示方式;前景色;背景色m   前景色 背景色 颜色 --------------------------------------- 30 40  黑色 31 41 ...

  4. Python终端如何输出彩色字体

    实现过程:       终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.       转义序列是以ESC开头,即用\033来完成(ESC的ASCII码用十进制表示是27 ...

  5. Python SSH登陆--pexpect,pxssh

    from pexpect import pxssh host = '192.168.80.139'user = 'allen'password = 'allen'command = 'df -h' d ...

  6. python终端中退格键,方向键不能使用

    在安装Python的时候先安装 yum install readline-devel.x86_64 -y 如果python已经安装过了就重新安装 ./configure    make all mak ...

  7. Python终端输出打印彩色字体的方法

    一  实现过程 终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关. 转义序列是以ESC开头,即用\033来完成(ESC的ASCII码用十进制表示是27,用八进制表示就是0 ...

  8. Python 终端输出字体颜色

    终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.             转义序列是以ESC开头,即用\033来完成(ESC的ASCII码用十进制表示是27,用八进制表 ...

  9. python终端打印带颜色的print

    原理 实现过程:       终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.       转义序列是以ESC开头,即用\033来完成(ESC的ASCII码用十进制表示 ...

随机推荐

  1. NodeJS基础入门-Buffer

    Buffer.byteLength console.log(Buffer.byteLength('test')); console.log(Buffer.byteLength('我是C语言爱好者')) ...

  2. linux文件属性之linux文件删除原理

    Linux是通过link的数量来控制文件删除的,只有当一个文件不存在任何link的时候,这个文件才会被删除.一般来说,每个文件都有2个link计数器:i_count和i_nlink. i_count的 ...

  3. jquery.imgpreload.min.js插件实现页面图片预加载

    页面分享地址: http://wenku.baidu.com/link?url=_-G8miwbgDmEj6miyFtjit1duJggBCJmFjR2jky_G1VftD9eS9kwGOlFWAOR ...

  4. Python中的字典与集合

    今天我们来讲一讲python中的字典与集合 Dictionary:字典 Set:集合 字典的语法: Dictionary字典(键值对) 语法: dictionary = {key:value,key: ...

  5. Centos启动时停止在登录界面但不显示登录信息(一直在转圈)

    进入单用户模式  执行 iscsiadm -m node -o delete,然后reboot

  6. BZOJ 3326: [Scoi2013]数数

    数位DP,然而式子真的复杂 #include<cstdio> #include<algorithm> #include<cstring> using namespa ...

  7. ios开发讲解之anchorPoint和position详解

    引言 相信初接触到CALayer的人都会遇到以下几个问题:  为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与posi ...

  8. spring boot 启动慢的原因

    停留在Spring logo那里差不多4分钟 SpringBoot启动慢的原因应该是某些应用占用了spring config server默认的端口8888,然后SpringCloud进程有些引用了s ...

  9. 12章 应用spary制作高级网页组件

    比较复杂的用户界面,tab面板  伸缩面板和折叠面板等组件.   tab面板和菜单实际上分为两种           一种是切换各个tab页中的内容时并不刷新浏览器窗口,仅仅是被隐藏起来了  利用ja ...

  10. AtCoder Regular Contest 083

    C - Sugar Water Time limit : 3sec / Memory limit : 256MB Score : 300 points Problem Statement Snuke ...