ToB企服应用市场:ToB评测及商务社交产业平台

标题: [Python自动化]使用Python Pexpect模块实现自动化交互脚本使用心得 [打印本页]

作者: 民工心事    时间: 2023-4-25 17:31
标题: [Python自动化]使用Python Pexpect模块实现自动化交互脚本使用心得
使用Python Pexpect模块实现自动化交互脚本使用心得

参考文档:https://pexpect.readthedocs.io/en/stable/
前言

在最近的工作中,需要使用DockerFile构建镜像。在构建镜像的过程中,有一些执行的命令是需要交互的。例如安装tzdata(apt install tzdata),不过在使用apt安装时,可以直接使用DEBIAN_FRONTEND=noninteractive 前缀来取消交互(至于是禁止交互还是选择交互的默认值,这一点就不太清楚了,TODO)。具体的命令行就是DEBIAN_FRONTEND=noninteractive apt install -y tzdata。在Dockerfile中也可以使用ARG进行统一设置。不过这种前缀设置方法仅仅适用于apt(大概TODO)。还有另一种我一开始就想到的方法,也就是利用类Unix自带的管道(pipe)功能,实现进程间通信,或是将stdin文件描述符重定向为某个文本或是字符串。按道理这是可行的,但是经过我的测试,不知道为啥行不通(等待探索TODO)。
Docker镜像中需要构建一个rust环境,因此需要安装rust。安装rust的方法一般有两种
因此我迫切需要一个可以自动化交互的方法。在网上找了很久答案后,发现pexpect可以实现这种自动化交互。因此在这里需要学习pexpect的相关用法。(shell脚本中也有expect相关概念,但是由于shell脚本我用起来感觉有点不太适应,因此就用python了)。
Pexpect简介

Pexpect allows your script to spawn a child application and control it as if a human were typing commands.
Pexpect can be used for automating interactive applications such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup scripts for duplicating software package installations on different servers. It can be used for automated software testing.
一个中心:自动化,各种需要交互,需要输入都可以自动化。
安装

使用pip包管理进行安装
  1. pip install pexpect -i https://pypi.tuna.tsinghua.edu.cn/simple/
复制代码
在这里用清华源进行加速。
This version of Pexpect requires Python 3.3 or above, or Python 2.7.
以下的流程均在Ubuntu上进行,Windows等系统使用pexpect请参考:https://pexpect.readthedocs.io/en/stable/overview.html#windows
基本操作

在py脚本中,定义想要匹配的提示,然后进行对应的输出。其中匹配可以是字符串完全匹配也可以是正则表达式状态机匹配。
example
  1. # This connects to the openbsd ftp site and
  2. # downloads the recursive directory listing.
  3. import pexpect
  4. child = pexpect.spawn('ftp ftp.openbsd.org')
  5. child.expect('Name .*: ')
  6. child.sendline('anonymous')
  7. child.expect('Password:')
  8. child.sendline('noah@example.com')
  9. child.expect('ftp> ')
  10. child.sendline('lcd /tmp')
  11. child.expect('ftp> ')
  12. child.sendline('cd pub/OpenBSD')
  13. child.expect('ftp> ')
  14. child.sendline('get README')
  15. child.expect('ftp> ')
  16. child.sendline('bye')
复制代码
注意事项

<ol>惊天巨坑
由于匹配的字符串可以是正则表达式也可以是普通字符串,因此有些符号是需要转义的。
比如我下面这个脚本
  1. import pexpect
  2. import sys
  3. child = pexpect.spawn('bash -c \'curl --proto \'=https\' --tlsv1.2 -sSf https://sh.rustup.rs | sh\'')
  4. child.expect("Continue\? \(y\/N\)")
  5. print("get 1")
  6. child.sendline("y")
  7. child.expect('>')
  8. print("get 2")
  9. child.sendline('1')
  10. child.expect(pexpect.EOF)
复制代码
如果child.expect("Continue\? \(y\/N\)")这句代码没有使用转义符号,那么就将卡死,这玩意卡了我半小时,属实是折磨了。
惊天巨坑

当命令行中使用(>>,




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4