时间:2022-11-01 09:18:02 | 栏目:Python代码 | 点击:次
Pexpect使Python成为控制其他应用程序的更好工具。可以理解为Linux下的expect的Python封装,通过pexpect我们可以实现对ssh,ftp,passwd,telnet等命令行进行自动交互,而无需人工干涉来达到自动化的目的
#python2 pip install pexpect #python3 pip3 install pexpect
3.1.3 构造方法参数
参数 | 说明 |
---|---|
command | 任何系统可执行的命令 参数可直接放入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.spawn('ls') >>> child.expect(pexpect.EOF) 0 >>> print(child.before.decode()) get-pip.py nohup.out stop-ssl-dos.sh index.html Python-2.7.18 ssl_flood.sh >>> child = pexpect.spawn('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('ls -l | grep Python') >>> child.expect(pexpect.EOF) 0 >>> print(child.before.decode()) /bin/ls: cannot access |: No such file or directory /bin/ls: cannot access grep: No such file or directory /bin/ls: cannot access Python: No such file or directory
(2)args=[]
# []传入参数列表 >>> child = pexpect.spawn('ls',args=['-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 18 1000 1000 4096 Feb 9 20:31 Python-2.7.18
(5)logfile=None
打开文件
>>> 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
在终端直接显示
>>> 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', logfile=sys.stdout, cwd='/home') >>> child.expect(pexpect.EOF) total 20 drwxr-xr-x 5 root root 4096 Jul 27 2017 . drwxr-xr-x 28 root root 4096 Dec 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 >>>
描述 | 说明 |
---|---|
基本方法 | expect(pattern,timeout=-1) 注:仅列出主要参数- pattern:可以为字符串、正则表达式、EOF、TIMEOUT,或者是以上类型的列表。用于匹配子命令返回结果 - 从子命令返回结果中进行匹配,若只提供字符串等非列表,匹配成功返回0;若提供列表,则返回匹配成功的列表序号;匹配失败则会引发异常; - 匹配事项: (1)匹配的方式是从返回信息中逐个字符读出进行匹配 (2)pattern为列表时,从左至右哪个最先匹配到就匹配哪个 (3)可以对结果进行多次匹配,但只能从前往后,前边已搜索匹配的内容不会再进行匹配 (4)匹配时自动应用re.DOTALL正则选项。( .+ 会匹配所有字符,.* 返回空字符)。(5)匹配行尾用 '\r\n' (无法用$ 匹配行尾)- timeout默认为-1时,使用默认的超时期限;设置为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-- 1 root root 0 Feb 21 19:18 log.txt drwxr-xr-x 2 root root 4096 Feb 21 19:18 test drwxr-xr-x 2 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.expect(['test','ttt']) 1 # 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: *** Can't find https://www.jd.com/: No answer >
使用sendline实现以上命令行功能:
>>> import pexpect >>> child = pexpect.spawn('nslookup') >>> child.expect('>') 0 >>> child.sendline('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 >>>
方法 | 描述 |
---|---|
send(s) | 类似于sendline(),只发送字符串给子程序; 不添加回车符(换行符); 打开了日志,则会添加到日志中; 返回已发送字节数; |
write(s) | 同send()方法,但无返回值; |
writelines(sequense) | 调用write()方法,将序列中内容发送 |
sendcontrol(char) | 发送类似ctrl+d、ctrl+d等组合键 |
sendof() | 发送一个结束符,一般用于确认上一次发送内容缓冲结束 |
sendintr() | 发送退出信号 |
方法 | 描述 |
---|---|
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.send('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 canonical name = www.xxx.com. Name: www.xxx.com Address: 100.59.200.6 Name: www.xxx.com Address: 100.59.200.7 # write方法 child.write('www.baidu.com\n') # writelines方法 child.writelines(['www.baidu.com','\n']) # sendintr方法 -- False表示子程序已经结束了 >>> child.sendintr() >>> child.isalive() False
方法 | 描述 |
---|---|
compile_pattern_list(patterns) | 编译列表每一项的正则表达式; 当多次应用expect匹配时,每次会先对其列表实行编译后匹配; 为了提高效率,可以预先调用它进行编译; 之后直接使用expect_list()方法进行匹配 |
eof() | 抛出过EOF错误,则返回真。 |
interact(escape_character=’\x\d’, input_filter=None, output_filter=None) | 实现子程序和用户直接交互; 开启了日志,输入和输出会记录在日志文件中; input_filter和output_filter用于对输入和输出进行过滤;传入的应是接受字符串参数并返回字符串的一个函数; 默认退出键为 ctrl+] |
方法 | 描述 |
---|---|
kill(sig) | 通过给子程序发送信号(signal); |