python 脚本:pexpect 在 child.wait() 上挂起?
python script: pexpect hangs on child.wait()?
我在 Linux 中有一个创建 ssh 密钥的工作脚本。在 macOS 中,它挂在 wait() 上。
import os
import sys
import pexpect
passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']
command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)
child.wait()
终于找到问题了。 ssh-keygen
binary好像有点不一样,后面输出了一些东西。
因为 wait() 是一个阻塞调用。
这不会从 child 读取任何数据,所以 如果 child 这将永远阻塞 ] 有未读输出并已终止。换句话说,child 可能打印输出然后调用 exit(),但是,child 在技术上仍然有效,直到它的输出被 parent.
读取。
.wait() docs here
解决此问题 read_nonblocking 从 child 应用程序读取最多 size 个字符。如果有可立即读取的字节,将读取所有这些字节(直到缓冲区大小)。
.read_nonblocking() docs here
工作解决方案
import os
import sys
import pexpect
passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']
command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)
# Avoid Hang on macOS
# https://github.com/pytest-dev/pytest/issues/2022
while True:
try:
child.read_nonblocking()
except Exception:
break
if child.isalive():
child.wait()
我在 Linux 中有一个创建 ssh 密钥的工作脚本。在 macOS 中,它挂在 wait() 上。
import os
import sys
import pexpect
passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']
command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)
child.wait()
终于找到问题了。 ssh-keygen
binary好像有点不一样,后面输出了一些东西。
因为 wait() 是一个阻塞调用。
这不会从 child 读取任何数据,所以 如果 child 这将永远阻塞 ] 有未读输出并已终止。换句话说,child 可能打印输出然后调用 exit(),但是,child 在技术上仍然有效,直到它的输出被 parent.
读取。.wait() docs here
解决此问题 read_nonblocking 从 child 应用程序读取最多 size 个字符。如果有可立即读取的字节,将读取所有这些字节(直到缓冲区大小)。
.read_nonblocking() docs here
工作解决方案
import os
import sys
import pexpect
passphrase = os.environ['HOST_CA_KEY_PASSPHRASE']
command = 'ssh-keygen'
child = pexpect.spawn(command, args=sys.argv[1:])
child.expect('Enter passphrase:')
child.sendline(passphrase)
# Avoid Hang on macOS
# https://github.com/pytest-dev/pytest/issues/2022
while True:
try:
child.read_nonblocking()
except Exception:
break
if child.isalive():
child.wait()