【问题标题】:python script: pexpect hangs on child.wait()?python 脚本:pexpect 挂在 child.wait() 上?
【发布时间】:2019-11-07 14:53:55
【问题描述】:

我在 Linux 中有一个创建 ssh-keys 的工作脚本。在 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()

【问题讨论】:

    标签: macos python-3.7 pexpect


    【解决方案1】:

    终于,我找到了问题所在。貌似ssh-keygen二进制有点不一样,后面输出了一些东西。

    因为 wait() 是一个阻塞调用。

    这不会从孩子那里读取任何数据,所以如果孩子有未读的输出并且已经终止,这将永远阻塞。换句话说,孩子可能已经打印了输出,然后调用了 exit(),但是,孩子在技术上仍然活着,直到它的输出被父母读取。

    .wait() docs here

    为了解决这个问题,read_nonblocking 最多从子应用程序中读取 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()
    

    【讨论】: