使用pexpect模块实现自动化交互:安装、核心组件及spawn类详解
目录

[id_1358784063]
Pexpect让 Python 成为能够控制其他应用程序的更优工具。它可以被看作是 Linux 下 expect 的 Python 封装形式。借助 pexpect,我们能够实现对 ssh、ftp、passwd、telnet 等命令行进行自动交互,无需人工参与,从而达到自动化的目的。
二、Pexpect的安装
#python2
pip install pexpect
#python3
pip3 install pexpect
3.1.2 其使用流程。
3.1.3 构造方法参数
参数说明
[id_1473120216]
任何系统可执行的命令
参数可直接放入command
不直接支持管道、通配符、标志输入、输出、错误重定向
args=[]
专门将command命令的参数放入这个列表中
以“/bin/bash”这种形式,其中包含“-c”以及“cat test | grep gree”这样的指令内容。
实现管道、通配符、标志输入、输出、错误重定向等功能
timeout=30
超出时间,抛出错误
maxread=2000
从TTY读取信息最大缓冲区
logfile=None
指定日志文件,可指定为sys.stdout
cwd=None
指定命令运行时的当前目录
env=None
指定命令运行时环境变量有哪些
encoding=None
命令运行时,信息编码
codec_errors=‘strict’
编码转换时的转向
(1)command
>>> import pexpect
child 被创建为通过 pexpect 启动的“ls”进程。
>>> child.expect(pexpect.EOF)
0
打印(child.before 进行解码后的结果)
get-pip.py 文件、nohup.out 文件、stop-ssl-dos.sh 文件
index.html 以及 Python-2.7.18 和 ssl_flood.sh
child 是通过 pexpect 模块启动的一个进程,该进程执行的命令是 "ls -l /home"
>>> child.expect(pexpect.EOF)
0
>>> print(child.before.decode())
total 12
文件的权限为 drwxr-xr-x,所有者为 root,所属组为 root,大小为 4096 字节,创建时间为 12 月 15 日 14 时 52 分
这是一个文件权限的表示形式,其中“drwxr-xr-x”表示文件类型为目录,拥有者有读、写、执行权限,所属组和其他用户有读和执行权限。“10”表示链接数,“root”表示文件所有者为 root 用户,“root”表示文件所属组为 root 组,“4096”表示文件大小为 4096 字节,“Aug 13 2020”表示文件的修改时间为 2020 年 8 月 13 日,“opt”表示文件所在的路径为 opt 目录。
文件权限为 drwxr-xr-x,所有者为 root,所属组为 root,大小为 4096,创建时间为 Jul 27 2017,目录名为 users
# 不支持管道、通配符、标志输入、输出、错误重定向
child 被创建为 pexpect.spawn('ls -l | grep Python')的实例。
>>> child.expect(pexpect.EOF)
0
>>> print(child.before.decode())
/bin/ls 无法访问“|”,原因是不存在该文件或目录。
/bin/ls 无法访问 grep,原因是不存在该文件或目录。
/bin/ls 无法访问 Python,原因是不存在这样的文件或目录。
(2)args=[]
# []传入参数列表
child 被创建为通过 pexpect 启动的进程,执行的命令是"ls",并且带有参数["-l","/home"]
>>> child.expect(pexpect.EOF)
0
>>> print(child.before.decode())
total 12
drwxr-xr-x 12 root root 4096 Dec 15 14:52 files
drwxr-xr-x 10 root root 4096 Aug 13 2020 opt
drwxr-xr-x 2 root root 4096 Jul 27 2017 users
# 实现管道、通配符、标志输入、输出、错误重定向等功能
child 被创建为一个 pexpect.spawn 对象,执行的命令是 '/bin/bash' ,命令参数是 ['-c','ls -al | grep Python'] 。
>>> child.expect(pexpect.EOF)
0
>>> print(child.before.decode())
目录权限为 drwxr-xr-x,所有者用户 ID 为 1000,所属组用户 ID 也为 1000,大小为 4096,创建时间为 2020 年 2 月 9 日 20 时 31 分,名为 Python-2.7.18
(5)logfile=None
打开文件
>>> f = open('log.txt','wb')
child 是通过 pexpect 模块启动的命令“ls -l /home”,并且将日志输出到 f 中。
>>> child.expect(pexpect.EOF)
0
>>> f.close()
>>> exit()
使用 cat 命令来显示 /root@xxxx-2021 目录中的 log.txt 文件的内容。
total 12
drwxr-xr-x 12 root root 4096 Dec 15 14:52 files
drwxr-xr-x 10 root root 4096 Aug 13 2020 opt
drwxr-xr-x 2 root root 4096 Jul 27 2017 users
在终端直接显示
>>> f = open('log.txt','wb')
>>> child = pexpect.spawn('ls -l /home', logfile=f)
>>> child.expect(pexpect.EOF)
0
>>> f.close()
>>> exit()
[root@xxxx-2021 ~]# cat log.txt
total 12
drwxr-xr-x 12 root root 4096 Dec 15 14:52 files
drwxr-xr-x 10 root root 4096 Aug 13 2020 opt
drwxr-xr-x 2 root root 4096 Jul 27 2017 users
(6)cwd=None
child 是通过 pexpect.spawnu 函数创建的,该函数的参数为 'ls -al',同时设置了日志文件为 sys.stdout,工作目录为 '/home'。
>>> child.expect(pexpect.EOF)
total 20
该目录的权限为 drwxr-xr-x,所有者为 root,所属组为 root,大小为 4096 字节,创建时间为 2017 年 7 月 27 日,是当前目录。
目录的权限为 drwxr-xr-x,拥有者为 root,所属组也为 root,大小为 4096 字节,创建时间是 12 月 16 日 07:56,上级目录为..
drwxr-xr-x 12 root root 4096 Dec 15 14:52 files
drwxr-xr-x 10 root root 4096 Aug 13 2020 opt
drwxr-xr-x 2 root root 4096 Jul 27 2017 users
0
>>>
3.1.4 基本属性和方法描述说明
基本方法
expect 函数,其中包含一个参数 pattern,还有一个 timeout 参数,其值为 -1 。仅列出了主要参数。
可以是字符串,也可以是正则表达式,还可以是 EOF、TIMEOUT,或者是这些类型的列表,用于匹配子命令返回结果
从子命令返回结果里进行匹配。如果只提供字符串这类非列表,匹配成功的话就返回 0;要是提供的是列表,那就返回匹配成功的列表序号;要是匹配失败,就会引发异常。
- 匹配事项:
(1)匹配的方式是从返回信息中逐个字符读出进行匹配
当 pattern 为列表时,从左到右进行匹配,最先匹配到的就被确定为匹配的那个。
可以多次对结果进行匹配,不过只能从前往后进行,前面已经搜索匹配过的内容不会再次进行匹配。
匹配时会自动运用 re.DOTALL 正则选项。. + 能够匹配所有的字符,而. * 则会返回空字符。
匹配行尾时使用'\r\n',而不能用$来匹配行尾。
当 timeout 默认为-1 时,会使用默认的超时期限;若 timeout 设置为 None ,则会阻塞至返回信息。
sendline(s='')
基本属性
before:匹配点之前的文本
after:匹配成功的内容
match:已匹配的匹配对象,匹配失败为None
特殊匹配
pexpect.EOF
pexpect.TIMEOUT
它们实际是两个异常类
(1)expect()连续匹配
# 连续匹配
child 是通过 pexpect.spawn 函数来执行 'ls -l' 命令的。
>>> child.expect(pexpect.EOF)
0
>>> print(child.before)
total 8
文件权限为 -rw-r--r--,所有者为 root,所属组为 root,文件大小为 0,创建时间为 Feb 21 19:18,文件名是 log.txt
目录的权限为 drwxr-xr-x,拥有者是 root,所属组也是 root,大小为 4096,创建时间是 Feb 21 19:18,名称为 test
文件权限为 drwxr-xr-x,所有者为 root,所属组为 root,大小为 4096,创建时间为 Feb 21 19:19,文件名是 tttt
>>>
>>> child = pexpect.spawn('ls -l')
>>> child.expect('test')
0
>>> print(child.after)
test
>>> child.expect('ttt')
0
>>> print(child.after)
ttt
>>>
# 连续匹配 列表形式
>>> child = pexpect.spawn('ls -l')
>>> child.expect('test')
0
>>> print(child.after)
test
>>> child.expect('ttt')
0
>>> print(child.after)
ttt
>>>
>>> child = pexpect.spawn('ls -l')
>>> child.expect('test')
0
child 期望 ['test', 'ttt'] 。
1 是 ttt 的列表索引,由于之前已经匹配过 test,所以文件游标不会再匹配(test 在前面,tttt 在后面)
>>>
(2)sendline(s=’’)
bash展示
[root@xxxx-2021 ~]# nslookup
> https://www.jd.com/
Server: 10.138.48.2
Address: 10.138.48.2#53
Non-authoritative answer:
无法找到 https://www.jd.com/,没有得到回应。
>
使用sendline实现以上命令行功能:
>>> import pexpect
child 被创建为 pexpect.spawn('nslookup') 这个操作的结果
>>> child.expect('>')
0
child 发送了一行内容为 'https://www.jd.com/' 的指令
20
>>> child.expect('>')
0
>>> print(child.before.decode())
https://www.jd.com/
Server: 10.138.48.2
Address: 10.138.48.2#53
Non-authoritative answer:
*** Can't find https://www.jd.com/: No answer
>>>
3.1.5 其他发送信息的方法方法描述
send(s)
类似于sendline(),只发送字符串给子程序;
不添加回车符(换行符);
打开了日志,则会添加到日志中;
返回已发送字节数;
write(s)
同send()方法,但无返回值;
writelines(sequense)
调用write()方法,将序列中内容发送
sendcontrol(char)
发送类似ctrl+d、ctrl+d等组合键
sendof()
发送一个结束符,一般用于确认上一次发送内容缓冲结束
sendintr()
发送退出信号
3.1.6 其他获取结果的方法方法描述
expect_exact()
用法与expect()方法相同,匹配速度更快;
除pattern不能用正则表达式
expect_list()
匹配列表只用已编译正则表达式和EOF、TIMEOUT;
提高匹配速度;
expect()方法是通过它工作的
read(size=-1)
从子程序输出中读取指定量数据。
size为-1时读取时直到EOF(当子程序退出后使用)
readline(size=-1)
-1时直接读取一行数据;
0时返回为空;
其他值时被忽略,返回一行;
# send方法
>>> child = pexpect.spawn('nslookup')
>>> child.expect('>')
0
child 把 "www.baidu.com" 发送了出去 。
13
>>> child.send('\n')
1
>>> child.expect('>')
0
>>> print(child.before.decode())
www.baidu.com
Server: 10.138.48.2
Address: 10.138.48.2#53
Non-authoritative answer:
www.baidu.com 的规范名称是 www.xxx.com.
Name: www.xxx.com
Address: 100.59.200.6
Name: www.xxx.com
Address: 100.59.200.7
# write方法
child 把 "www.baidu.com" 写入并进行了换行的操作。
# writelines方法
child 写入了 ['www.baidu.com', '\n'] 这些内容。
sendintr 方法,其 False 意味着子程序已经结束了。
>>> child.sendintr()
>>> child.isalive()
False
3.1.7 其他常用方法方法描述
编译模式列表(patterns)。
编译列表每一项的正则表达式;
多次应用 expect 匹配时,每次会先对其列表进行编译,然后再进行匹配。
为了提高效率,可以预先调用它进行编译;
之后直接使用expect_list()方法进行匹配
eof()
抛出过EOF错误,则返回真。
interact 函数具有 escape_character 为 ’\x\d’ ,同时输入过滤器为 None ,输出过滤器也为 None 。
实现子程序和用户直接交互;
开启了日志,输入和输出会记录在日志文件中;
Input_filter 用于对输入进行过滤,output_filter 用于对输出进行过滤。传入的应是这样一个函数,它接受字符串参数并返回字符串。
默认退出键为ctrl+]
3.1.8 控制子程序方法
方法描述
kill(sig)
通过给子程序发送信号(signal);
这篇关于 Python 模块之 pexpect 的文章到此就介绍完啦。如果想了解更多关于 Python 模块 pexpect 的内容,可以搜索编程网以前的文章,或者继续浏览下面的相关文章。希望大家以后多多支持编程网!