【问题标题】:Killing subprocess after first line在第一行之后杀死子进程
【发布时间】:2016-02-19 06:18:38
【问题描述】:

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

下面是子程序输出的样子:

Authentication Required

Enter authorization information for "Web API"

<username_prompt_here>
<password_prompt_here>

我想在打印“需要身份验证”后立即终止子进程,但问题是我的代码运行错误 - 子进程要求提供凭据,在用户提供凭据后,子进程被终止。

这是我的代码:

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)

我做错了什么?

【问题讨论】:

  • 你能发布完整的代码吗?还是完整的?我没有看到您在哪里提示用户输入用户名和密码。
  • 我没有提示 - 子程序会这样做(查看附加输出)。
  • 并且您想在 Authentication Required 行之后立即终止该进程?
  • 是否真的要等用户输入用户名和密码才退出子程序?
  • 是的,我不想让子程序询问密码,目前情况是询问密码,然后被杀死。

标签: subprocess python-3.4


【解决方案1】:

我做错了什么?

如果子进程及时刷新其标准输出缓冲区,则您的代码是可以的(如果您想在'Authentication Required' 行之后终止子进程,无论其位置)。见Python: read streaming input from subprocess.communicate()

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

解决方法:

  • 查看是否可以传递命令行参数,例如 --line-bufferedgrep 接受)来强制行缓冲模式
  • 或查看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

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 2014-05-18
    • 1970-01-01
    • 2020-10-04
    相关资源
    最近更新 更多