subprocess的Popen和call有什么区别(我该如何使用它们)?

226 投票
2 回答
160744 浏览
提问于 2025-04-17 03:50

我想从Python中调用一个外部程序。我用过 Popen()call() 这两个方法。

这两者有什么区别呢?

我具体想要做的是从Python运行以下命令。我对重定向是怎么回事还不太明白。

./my_script.sh > output

我看了文档,上面说 call() 是一个方便的函数,或者说是一个快捷函数。那用 call() 代替 Popen() 会失去什么功能吗?

2 个回答

61

另一个回答很全面,但这里有个简单的原则:

  • call 是阻塞的:

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

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

重定向有两种方法。这两种方法都适用于 subprocess.Popensubprocess.call

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

  2. 因为你只是把输出重定向到一个文件,所以设置关键字参数

    stdout = an_open_writeable_file_object
    

    这里的对象指向 output 文件。

subprocess.Popensubprocess.call 更通用。

Popen 不会阻塞,这意味着你可以在它运行的时候与这个进程互动,或者继续做其他事情。调用 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 的一个简单封装。

撰写回答