【问题标题】:Is it possbile to let pexpect output the texts it matches?是否可以让 pexpect 输出它匹配的文本?
【发布时间】:2020-09-10 08:30:49
【问题描述】:

我对expect脚本很熟悉,所以第一次使用pexpect的时候感觉有点奇怪。以这个简单的脚本为例,

#!/usr/bin/expect
set timeout 10
spawn npm login
expect "Username:"
send "qiulang2000\r"
expect "Password:"
send "xxxxx\r"
expect "Email:"
send "qiulang@gmail.com\r"
expect "Logged in as"
interact

运行它时,我会得到以下输出。这感觉很自然,因为这就是我运行这些命令的方式

spawn npm login
Username: qiulang2000
Password:
Email: (this IS public) qiulang@gmail.com
Logged in as qiulang2000 on https://registry.npmjs.com/.

但是当我使用 pexpect 时,无论我如何添加 print(child.after)print(child.before) 我都无法像期望一样获得输出,例如当我运行以下命令时,

#! /usr/bin/env python3
import pexpect
child = pexpect.spawn('npm login')
child.timeout = 10
child.expect('Username:')
print(child.after.decode("utf-8"))
child.sendline('qiulang2000')
child.expect('Password:')
child.sendline('xxxx')
child.expect('Email:')
child.sendline('qiulang@gmail.com')
child.expect('Logged in as')
print(child.before.decode("utf-8"))
child.interact()

我得到了这些输出,感觉不自然,因为这不是我在运行这些命令时看到的。

Username:
 (this IS public)       qiulang@gmail.com

 qiulang2000 on https://registry.npmjs.com/.

那么是否有可能实现期望的脚本输出?

---更新---

根据我从@pynexj 得到的评论,我终于成功了,请在下面查看我的答案。

【问题讨论】:

  • 谢谢!我终于让它工作了。最后一个问题,我觉得我根本不需要调用 child.interact() (与期望不同)。是这样吗?
  • @pynexj 你能检查我更新的问题吗?
  • 必须与 py3 相关。你的 python 和 pexpect 的版本是什么?
  • 对于py3,试试child.logfile_read = sys.stdout.buffer

标签: python expect pexpect


【解决方案1】:

有了我得到的评论,我终于成功了

#! /usr/bin/env python3

import pexpect
import sys
print('npm login',timeout = 10)
child = pexpect.spawn('npm login')
child.logfile_read = sys.stdout.buffer // use sys.stdout.buffer for python3
child.expect('Username:')
child.sendline('qiulang2000')
child.expect('Password:')
child.sendline('xxxx')
child.expect('Email:')
child.sendline('qiulang@gmail.com')
child.expect('Logged in as')

如果我需要调用 child.interact(),那么在它之前调用 child.logfile_read = None 很重要,否则 sys.stdout 会回显我输入的所有内容。

这里的答案How to see the output in pexpect?说我需要为python3传递一个编码,但我发现如果我使用encoding='utf-8'会导致TypeError: a bytes-like object is required, not 'str'如果我根本不设置编码,一切正常。

所以一个简单的 ssh 登录脚本是这样的

#!/usr/bin/env python3

import pexpect
import sys
child = pexpect.spawn('ssh qiulang@10.0.0.32')
child.logfile_read = sys.stdout.buffer
child.expect('password:')
child.sendline('xxxx')
#child.expect('Last login')  don't do that
child.logfile_read = None # important !!!
child.interact()

一个问题仍未解决,我在发送密码后添加了最后一个期望调用以匹配 ssh 登录输出,例如child.expect('上次登录')

但如果我添加它,那行会显示两次。我已经放弃了尝试,就像一条评论说“pexpect 的行为有点违反直觉”。

Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-141-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

33 packages can be updated.
0 updates are security updates.

Last login: Fri Sep 11 11:44:19 2020 from 10.0.0.132
: Fri Sep 11 11:44:19 2020 from 10.0.0.132

【讨论】:

  • 对于“该行将显示两次”,请在 child.logfile_read = None 之前尝试 child.expect('.*')
  • encoding 参数是官方 pexpect 文档建议的,除非您确切知道生成进程的输出(和输入)的编码,否则我认为这不是必需的。
猜你喜欢
  • 1970-01-01
  • 2019-10-09
  • 2020-02-19
  • 2013-11-03
  • 1970-01-01
  • 2016-08-02
  • 2018-03-29
  • 1970-01-01
相关资源
最近更新 更多