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

目录

使用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 的内容,可以搜索编程网以前的文章,或者继续浏览下面的相关文章。希望大家以后多多支持编程网!

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

32阅读

外国教程python,python编程教学视频

2026年09月02日

27阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

27阅读

python教程大全集,python教程600集

2026年09月02日

27阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

23阅读