在第一行之后杀死子进程

时间:2016-02-19 06:18:38

标签: subprocess python-3.4

我正在执行从python连接到外部服务器的程序 如果用户未通过身份验证,则程序会要求输入用户名和密码。

以下是子程序输出的外观:

Authentication Required

Enter authorization information for "Web API"

<username_prompt_here>
<password_prompt_here>

我想在打印'Authentication Required'后立即终止子进程,但问题是,我的代码工作错误 - 子进程要求提供凭据,用户提供后,子进程被终止。

这是我的代码:

with subprocess.Popen(self.command, stdout=subprocess.PIPE, shell=True, bufsize=1, universal_newlines=True) as process:
    for line in process.stdout:
        if 'Authentication Required' in line:
            print('No authentication')
            process.kill()
        print(line)

我做错了什么?

1 个答案:

答案 0 :(得分:1)

  

我做错了什么?

如果子进程及时刷新其stdout缓冲区,那么您的代码是正常的(如果您想在'Authentication Required'行之后杀死子进程,无论其位置如何)。见Python: read streaming input from subprocess.communicate()

观察到的行为表明孩子使用了块缓冲模式,因此您的父脚本看到'Authentication Required'行太晚或者使用process.kill()杀死shell并不会杀死其后代(由命令创建的进程)。

解决方法:

  • 查看是否可以传递命令行参数,例如--line-buffered(由grep接受),以强制执行行缓冲模式
  • 或查看stdbufunbufferscript实用程序是否适合您的情况
  • 或者提供一个伪tty来欺骗过程,使其认为它直接在终端中运行 - 它也可能强制行缓冲模式。

请参阅以下代码示例:

  

并且 - 并不总是我想在第一行之后杀死程序。仅当第一行是“需要身份验证”时才

假设修复了块缓冲问题,如果第一行包含Authentication Required,则要终止子进程:

with Popen(shlex.split(command), 
           stdout=PIPE, bufsize=1, universal_newlines=True) as process:
    first_line = next(process.stdout)
    if 'Authentication Required' in first_line:
        process.kill()
    else: # whatever
        print(first_line, end='')
        for line in process.stdout:
            print(line, end='')

如果您需要shell=True,请参阅How to terminate a python subprocess launched with shell=True