正确使用和关闭子流程对象的方法

发布于 2021-01-29 16:35:47

我在循环中有以下代码:

while true:
    # Define shell_command
    p1 = Popen(shell_command, shell=shell_type, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid)
    result = p1.stdout.read(); 
    # Define condition
    if condition:
       break;

哪里shell_command是类似的东西ls(它只是打印东西)。

我在不同的地方阅读过可以Popen以多种方式关闭/终止/退出对象的信息,例如:

p1.stdout.close()
p1.stdin.close()
p1.terminate
p1.kill

我的问题是:

  1. subprocess使用完后,关闭对象的正确方法是什么?
  2. 考虑到我的脚本的性质,有没有办法只打开一个subprocess对象并用不同的shell命令重用它?以任何方式比subprocess每次打开新对象都更有效率吗?

更新资料

我仍然对根据我使用p1.communicate()还是p1.stdout.read()与我的过程进行交互所遵循的步骤顺序感到困惑。

根据我在答案和评论中的理解:

如果我使用
p1.communicate(),则不必担心释放资源,因为communicate()会等到过程完成后,抓取输出并正确关闭subprocess对象

如果我遵循这p1.stdout.read()条路线(我认为适合我的情况,因为shell命令只用于打印内容),则应按以下顺序调用:

  1. p1.wait()
  2. p1.stdout.read()
  3. p1.terminate()

是对的吗?

关注者
0
被浏览
47
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    使用完后,关闭子流程对象的正确方法是什么?

    stdout.close()stdin.close()不会终止一个进程 ,除非 它退出本身的输入端或写入错误。

    .terminate()并且.kill()都做工作,以kill更加一下就POSIX系统“釜底抽薪”,因为SIGKILL是送的,不能被应用程序忽略。例如,在此博客文章中解释特定的差异。在Windows上,没有区别。

    另外,请记住.wait()在杀死进程后关闭管道,以免造成僵尸并强制释放资源。

    经常遇到的一种特殊情况是从STDIN读取并将其结果写入STDOUT的进程,当遇到EOF时会自行关闭。通过这些程序,通常明智的做法是subprocess.communicate

    >>> p = Popen(["sort"], stdin=PIPE, stdout=PIPE)
    >>> p.communicate("4\n3\n1")
    ('1\n3\n4\n', None)
    >>> p.returncode
    0
    

    这也可以用于打印某些内容并在之后立即退出的程序:

    >>> p = Popen(["ls", "/home/niklas/test"], stdin=PIPE, stdout=PIPE)
    >>> p.communicate()
    ('file1\nfile2\n', None)
    >>> p.returncode
    0
    

    考虑到我的脚本的性质,有没有办法只打开一个子流程对象一次,并用不同的shell命令重用它?以任何方式比每次打开新的子流程对象更有效率吗?

    我认为该subprocess模块不支持此功能,也看不到可以在此处共享哪些资源,因此我认为它不会给您带来明显的优势。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看