<p>这个问题的答案取决于您使用的Python版本。最简单的方法是使用<a href="https://docs.python.org/3/library/subprocess.html#subprocess.check_output" rel="noreferrer">^{<cd1>}</a>函数:</p>
<pre><code>>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
</code></pre>
<p><code>check_output</code>运行一个只接受参数作为输入的程序。<sup>1</sup>它返回打印到<code>stdout</code>的结果。如果需要向<code>stdin</code>写入输入,请跳到<code>run</code>或<code>Popen</code>部分。如果要执行复杂的shell命令,请参阅本答案末尾关于<code>shell=True</code>的说明。</p>
<p><code>check_output</code>函数可以在几乎所有仍在广泛使用的Python版本(2.7+).<sup>2</sup>上工作,但对于较新的版本,它不再是推荐的方法。</p>
<h3>Python的现代版本(3.5或更高版本):<code>run</code></h3>
<p>如果您使用的是<strong>Python 3.5</strong>或更高版本,并且<strong>不需要向后兼容,建议使用<a href="https://docs.python.org/3/library/subprocess.html#using-the-subprocess-module" rel="noreferrer">new ^{<cd5>} function</a>。它为<code>subprocess</code>模块提供了一个非常通用的高级API。要捕获程序的输出,请将<code>subprocess.PIPE</code>标志传递给<code>stdout</code>关键字参数。然后访问返回的<a href="https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess" rel="noreferrer">^{<cd15>}</a>对象的<code>stdout</code>属性:</p>
<pre><code>>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
</code></pre>
<p>返回值是一个<code>bytes</code>对象,因此如果您想要一个合适的字符串,就需要<code>decode</code>它。假设调用的进程返回一个UTF-8编码的字符串:</p>
<pre><code>>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
</code></pre>
<p>所有这些都可以压缩为一行:</p>
<pre><code>>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
</code></pre>
<p>如果要将输入传递给进程的<code>stdin</code>,请将<code>bytes</code>对象传递给<code>input</code>关键字参数:</p>
<pre><code>>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
</code></pre>
<p>您可以通过传递<code>stderr=subprocess.PIPE</code>(捕获到<code>result.stderr</code>)或<code>stderr=subprocess.STDOUT</code>(捕获到<code>result.stdout</code>)以及常规输出来捕获错误。当不考虑安全性时,还可以通过传递<code>shell=True</code>来运行更复杂的shell命令,如下面的注释所述。</p>
<p>与以前的做事方式相比,这只增加了一点复杂性。但我认为这是值得的:现在您几乎可以只使用<code>run</code>函数做任何需要做的事情。</p>
<h3>旧版本的Python(2.7-3.4):<code>check_output</code></h3>
<p>如果您使用的是较旧版本的Python,或者需要适度的向后兼容性,那么您可以使用上面简要描述的<code>check_output</code>函数。它从Python2.7开始就可用了。</p>
<pre><code>subprocess.check_output(*popenargs, **kwargs)
</code></pre>
<p>它接受与<code>Popen</code>相同的参数(见下文),并返回包含程序输出的字符串。这个答案的开头有一个更详细的用法示例。在Python 3.5及更高版本中,<code>check_output</code>相当于使用<code>check=True</code>和<code>stdout=PIPE</code>执行<code>run</code>,并只返回<code>stdout</code>属性。</p>
<p>您可以传递<code>stderr=subprocess.STDOUT</code>,以确保返回的输出中包含错误消息——但是在某些版本的Python中,传递<code>stderr=subprocess.PIPE</code>到<code>check_output</code>可能会导致<a href="https://docs.python.org/2/library/subprocess.html#subprocess.check_output" rel="noreferrer">deadlocks</a>。当不考虑安全性时,还可以通过传递<code>shell=True</code>来运行更复杂的shell命令,如下面的注释所述。</p>
<p>如果您需要从<code>stderr</code>进行管道传输或将输入传递给进程,<code>check_output</code>将无法完成任务。在这种情况下,请参见下面的<code>Popen</code>示例。</p>
<h3>复杂应用程序&Python的遗留版本(2.6及以下版本):<code>Popen</code></h3>
<p>如果您需要深入的向后兼容性,或者如果您需要比<code>check_output</code>提供的功能更复杂的功能,则必须直接使用<code>Popen</code>对象,该对象封装了子流程的低级API。</p>
<p><code>Popen</code>构造函数接受不带参数的单个命令,或接受包含命令的列表作为其第一项,后跟任意数量的参数,作为列表中的单独项。<a href="https://docs.python.org/3/library/shlex.html" rel="noreferrer">^{<cd46>}</a>可以帮助将字符串解析为格式适当的列表。<code>Popen</code>对象还接受一个<a href="https://docs.python.org/3/library/subprocess.html#subprocess.Popen" rel="noreferrer">host of different arguments</a>用于进程IO管理和低级配置。</p>
<p>要发送输入和捕获输出,<code>communicate</code>几乎总是首选方法。如所示:</p>
<pre><code>output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
</code></pre>
<p>或者</p>
<pre><code>>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
</code></pre>
<p>如果设置了<code>stdin=PIPE</code>,<code>communicate</code>还允许您通过<code>stdin</code>将数据传递给进程:</p>
<pre><code>>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
</code></pre>
<p>注意<a href="https://stackoverflow.com/a/21867841/577088">Aaron Hall's answer</a>,这表示在某些系统上,可能需要将<code>stdout</code>、<code>stderr</code>和<code>stdin</code>全部设置为<code>PIPE</code>(或<code>DEVNULL</code>),以使<code>communicate</code>完全工作。</p>
<p>在一些罕见的情况下,您可能需要复杂的实时输出捕获。<a href="https://stackoverflow.com/a/4760274/577088">Vartec</a>的答案表明了一条前进的道路,但是<code>communicate</code>以外的方法如果不小心使用,很容易出现死锁。</p>
<p>与所有上述函数一样,当不考虑安全性时,可以通过传递<code>shell=True</code>来运行更复杂的shell命令。</p>
<h3>注释</h3>
<p><strong>1。运行shell命令:参数<code>shell=True</code></p>
<p>通常,对<code>run</code>、<code>check_output</code>或<code>Popen</code>构造函数的每个调用都执行一个<em>单个程序</em>。这意味着没有花哨的bash风格的管道。如果要运行复杂的shell命令,可以传递所有三个函数都支持的<code>shell=True</code>。</p>
<p>但是,这样做会提高<a href="https://docs.python.org/3/library/subprocess.html#security-considerations" rel="noreferrer">security concerns</a>。如果您所做的不仅仅是简单的脚本编写,那么最好分别调用每个进程,并将每个进程的输出作为输入传递给下一个进程,通过</p>
<pre><code>run(cmd, [stdout=etc...], input=other_output)
</code></pre>
<p>或者</p>
<pre><code>Popen(cmd, [stdout=etc...]).communicate(other_output)
</code></pre>
<p>直接连接管道的诱惑力很强;抵制住它。否则,您可能会看到死锁,或者不得不做一些像<a href="https://stackoverflow.com/questions/6341451/piping-together-several-subprocesses">this</a>这样的讨厌的事情。</p>
<p><strong>2。Unicode注意事项</strong></p>
<p><code>check_output</code>在Python 2中返回一个字符串,但在Python 3中返回一个<code>bytes</code>对象。如果你还没有的话,花点时间<a href="https://docs.python.org/3/howto/unicode.html" rel="noreferrer">learn about unicode</a>是值得的。</p>