在本文中,我们展示了如何使用pexpect模块在Python中管理交互式程序。
pexpect
模块用于管理Python中的交互程序。它产生子应用程序,控制它们;并响应其输出中的预期模式。
pexpect模块用于自动化交互式应用程序,例如ssh、ftp或passwd。它可用于在不同服务器上自动执行软件包安装的设置脚本。
有两个基本函数:run
和spawn
。run函数执行命令并返回输出。它对于简单的交互很有用。
spawn
函数是一个更强大的选项。它产生一个外部子命令,然后通过发送行和期待响应与子命令交互。
Python预期运行
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
Pythonpexpect日志文件
可以将输出重定向到日志文件中。run和spawnfunctions都有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预期产卵
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
PythonpexpectFTP示例
在下一个示例中,我们将与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
命令。使用此命令,我们连接到theftp.freebsd.org服务器。我们还提供编码。
child.expect('Name .*: ')
从服务器,我们期望一行以Name
stringpattern开头,后跟一些字符。请注意,输入是正则表达式。
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期待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
命令终止连接。
在本教程中,我们介绍了Pythonpexpect模块。
列出所有Python教程。