子进程 Popen 和 call 有啥区别(我该如何使用它们)?

Posted

技术标签:

【中文标题】子进程 Popen 和 call 有啥区别(我该如何使用它们)?【英文标题】:What's the difference between subprocess Popen and call (how can I use them)?子进程 Popen 和 call 有什么区别(我该如何使用它们)? 【发布时间】:2011-12-02 15:52:34 【问题描述】:

我想从 Python 调用一个外部程序。我已经使用 Popen()call() 来做到这一点。

两者有什么区别?

我的具体目标是从 Python 运行以下命令。我不确定重定向是如何工作的。

./my_script.sh > output

我读过the documentation,它说call() 是一个便利功能或快捷功能。使用call() 而不是Popen(),我们会失去任何权力吗?

【问题讨论】:

文档的哪一部分让您感到困惑? call() 的定义似乎很明确。您能否提供报价或链接,以便我们知道在回答中重点关注什么? 【参考方案1】:

有两种方法可以进行重定向。两者都适用于subprocess.Popensubprocess.call

    设置关键字参数shell = Trueexecutable = /path/to/the/shell 并指定命令,就像你在那里一样。

    由于您只是将输出重定向到文件,因此请设置关键字参数

    stdout = an_open_writeable_file_object
    

    对象指向output 文件的位置。

subprocess.Popensubprocess.call 更通用。

Popen 不会阻塞,允许您在进程运行时与其进行交互,或继续在 Python 程序中进行其他操作。对Popen 的调用返回一个Popen 对象。

call 确实阻止。虽然它支持与Popen 构造函数相同的所有参数,因此您仍然可以设置进程的输出、环境变量等,但您的脚本会等待程序完成,call 返回一个代表进程的代码'退出状态。

returncode = call(*args, **kwargs) 

和调用基本一样

returncode = Popen(*args, **kwargs).wait()

call 只是一个便利功能。它在 CPython 中的实现在 subprocess.py:

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

如您所见,它是Popen 周围的薄包装。

【讨论】:

Popen 和 call 基本上是异步和同步函数,分别用于运行 Linux 命令。 使用popen有什么好处?等到被调用的程序先完成不安全吗? @Tom 通常不会。如果你想读取一些输出,然后向程序发送更多输入,读取更多由该输入产生的输出,重复? @user3016020 我认为这也适用于 Windows 命令?对吗? 我认为 popen 有一个可迭代的参数,而调用一个字符串。【参考方案2】:

另一个答案很完整,但这里有一个经验法则:

call 正在阻塞:

call('notepad.exe')
print('hello')  # only executed when notepad is closed

Popen 是非阻塞的:

Popen('notepad.exe')
print('hello')  # immediately executed

【讨论】:

以上是关于子进程 Popen 和 call 有啥区别(我该如何使用它们)?的主要内容,如果未能解决你的问题,请参考以下文章

subprocess.call() 和 subprocess.Popen() 之间有啥区别使 PIPE 对前者的安全性降低?

Python执行外部命令(subprocess,call,Popen)

多进程和子进程有啥区别?

nginx和apache有啥区别,我该用哪种?

阻塞和非阻塞子进程调用

subprocess模块