Python pexpect
最后修改于 2024 年 1 月 29 日
在本文中,我们将介绍如何使用 pexpect 模块在 Python 中管理交互式程序。
pexpect 模块用于在 Python 中管理交互式程序。它会生成子应用程序,控制它们;并响应其输出中的预期模式。
pexpect 模块用于自动化交互式应用程序,例如 ssh、ftp 或 passwd。它可以用于自动化不同服务器上软件程序安装的设置脚本。
有两个基本函数:run 和 spawn。run 函数执行命令并返回输出。它对于简单的交互很有用。
spawn 函数是一个更强大的选项。它会生成一个外部子命令,然后通过发送行和期望响应来与子命令进行交互。
Python pexpect run
run 函数运行给定的命令;等待它完成;然后将所有输出作为字符串返回。标准错误输出包含在输出中。
#!/usr/bin/python
import pexpect
r = pexpect.run('echo hello')
print(str(r, 'UTF-8'))
在程序中,我们运行 echo 命令。
r = pexpect.run('echo hello')
我们运行 echo 命令。输出被赋给 r 变量。
print(str(r, 'UTF-8'))
我们使用 str 函数将输出转换为字符串。
$ ./main.py hello
我们可以使用 bytes.decode 函数将 bytes 转换为 str。
#!/usr/bin/python
import pexpect
r = pexpect.run('pwd').decode("utf-8")
print(f"The current working directory: {r.rstrip()}")
程序运行 pwd 程序,该程序返回当前工作目录。
$ ./main.py The current working directory: /home/jano/Documents/prog/python/pexpect
Python pexpect logfile
可以将输出重定向到日志文件。run 和 spawn 函数都有 logfile 参数。
#!/usr/bin/python
import pexpect
f = open('mylog.txt', 'wb')
pexpect.run('ls -l', logfile=f)
f.close()
在程序中,我们运行 ls -l 命令并将输出写入日志文件。
$ ./main.py $ head -3 mylog.txt total 60 -rw-rw-r-- 1 jano jano 120 dec 23 10:02 doc.txt -rwxrwxr-x 1 jano jano 418 dec 23 14:52 ftp2.py
Python pexpect spawn
spawn 函数执行子程序并允许与之交互。
子程序的 expect 函数会扫描流,直到匹配到某个模式。模式是重载的,可以接受多种类型。模式可以是字符串、EOF、编译后的正则表达式或任何这些类型的列表。字符串将被编译为正则表达式类型。
#!/usr/bin/python
import pexpect
child = pexpect.spawn('date')
child.expect(pexpect.EOF)
output = child.before
print(f'Today is : {output.decode("utf-8")}')
child.close()
在程序中,我们运行 date 命令来获取当前日期时间。
child = pexpect.spawn('date')
我们生成 date 命令。
child.expect(pexpect.EOF)
使用 pexpect.EOF,我们期望子程序已退出。在每次调用 expect 后,before 和 after 属性将被设置为子应用程序打印的文本。
output = child.before
before 属性包含到预期模式的所有文本。
$ ./main.py Today is : Št 29. december 2022, 11:39:30 CET
Python pexpect FTP 示例
在下一个示例中,我们将与 FTP 命令进行交互。
#!/usr/bin/python
import pexpect
child = pexpect.spawn('ftp ftp.freebsd.org', encoding='utf-8')
child.expect('Name .*: ')
child.sendline('anonymous')
child.expect('Password:')
child.sendline('')
child.expect('ftp> ')
child.sendline('ls /pub/FreeBSD/')
child.expect('ftp> ')
print(child.before)
child.close()
在程序中,我们连接到一个匿名 FTP 服务器并发出 ls 命令。
child = pexpect.spawn('ftp ftp.freebsd.org', encoding='utf-8')
我们生成 ftp 命令。通过此命令,我们连接到 ftp.freebsd.org 服务器。我们还提供了编码。
child.expect('Name .*: ')
从服务器,我们期望一个以 Name 字符串模式开头后跟一些字符的行。请注意,输入是一个正则表达式。
child.sendline('anonymous')
使用 sendline,我们发送登录名。
child.expect('Password:')
child.sendline('')
我们期望密码提示并发送一个空密码,因为我们以匿名方式登录。
child.sendline('ls /pub/FreeBSD/')
我们发出 ls 命令。
print(child.before)
我们打印 ls 命令的输出。
$ ./main.py ls /pub/FreeBSD/ 229 Entering Extended Passive Mode (|||51545|) 150 Here comes the directory listing. -rw-r--r-- 1 ftp ftp 4259 May 07 2015 README.TXT -rw-r--r-- 1 ftp ftp 35 Dec 29 10:45 TIMESTAMP drwxr-xr-x 9 ftp ftp 10 Dec 29 10:45 development -rw-r--r-- 1 ftp ftp 2995 Dec 29 10:00 dir.sizes drwxr-xr-x 22 ftp ftp 28 Dec 26 23:00 doc drwxr-xr-x 6 ftp ftp 6 Nov 10 15:01 ports drwxr-xr-x 12 ftp ftp 14 Dec 29 10:45 releases drwxr-xr-x 12 ftp ftp 14 Dec 09 20:25 snapshots 226 Directory send OK.
Python pexpect SSH
在下面的示例中,我们将与 ssh 命令进行交互。
对于此示例,我们必须有一个启用密码身份验证的 ssh 帐户。
#!/usr/bin/python
import pexpect
username = 'user7@192.168.0.25'
passwd = 'passwd'
child = pexpect.spawn(f'ssh {username}')
f = open('mylog.txt', 'wb')
child.logfile = f
child.expect('password:')
child.sendline(passwd)
i = child.expect(['Permission denied', '[#\$] '])
if i == 0:
print('failed to login. permission denied')
child.close()
elif i == 1:
print('connected')
child.sendline('uname -a')
child.expect('[#\$] ')
r = child.before.decode('utf-8')
child.write('exit')
child.close()
f.close()
我们连接到本地网络上的计算机,并在主机上发出 uname 命令。
username = 'user7@192.168.0.25' passwd = 'passwd'
我们提供用户名和密码。
child = pexpect.spawn(f'ssh {username}')
我们使用 ssh 命令登录到主机。
f = open('mylog.txt', 'wb')
child.logfile = f
输出被定向到日志文件。
child.expect('password:')
child.sendline(passwd)
计算机发送一个提示,我们发送密码。
i = child.expect(['Permission denied', '[#\$] '])
我们期望两种结果:要么是权限被拒绝的消息,要么是标准提示。expect 函数返回匹配结果的索引。
elif i == 1:
print('connected')
child.sendline('uname -a')
child.expect('[#\$] ')
child.write('exit')
child.close()
如果登录成功,我们发出 uname 命令。稍后,我们发出 exit 命令来终止连接。
来源
在本文中,我们介绍了 Python pexpect 模块。
作者
列出所有 Python 教程。