子进程Popen和call之间的区别是什么(我该如何使用它们)?

时间:2011-10-06 23:44:34

标签: python subprocess popen

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

两者之间有什么区别?

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

./my_script.sh > output

我读了the documentation,它说call()是一个便利功能或快捷功能。使用call()代替Popen()

,我们是否会失去任何力量?

2 个答案:

答案 0 :(得分:235)

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

  1. 设置关键字参数shell = Trueexecutable = /path/to/the/shell,然后像在那里一样指定命令。

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

    stdout = an_open_writeable_file_object
    

    对象指向output文件。

  3. 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周围的薄包装。

答案 1 :(得分:6)

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

  • call被阻止:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
    
  • Popen无阻塞:

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