<p>关于<code>subprocess</code>的一些经验法则。</p>
<ul>
<li><strong>从不</strong>使用<code>shell=True</code>。它不必要地调用额外的shell进程来调用您的程序。</li>
<li>调用进程时,参数作为列表传递。^python中的{<cd3>}是一个列表,C中的<code>argv</code>也是这样。因此,您将<strong>列表</strong>传递给<code>Popen</code>以调用子进程,而不是字符串。</li>
<li>不要在不阅读时将<code>stderr</code>重定向到<code>PIPE</code>。</li>
<li>当你不写的时候,不要重定向<code>stdin</code>。</li>
</ul>
<p>示例:</p>
<pre><code>import subprocess, time, os, sys
cmd = ["rsync.exe", "-vaz", "-P", "source/" ,"dest/"]
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
print(">>> " + line.rstrip())
</code></pre>
<p>也就是说,当rsync检测到它连接到管道而不是终端时,它很可能会缓冲它的输出。这是默认行为-当连接到管道时,程序必须显式刷新stdout以获得实时结果,否则标准C库将缓冲。</p>
<p>要进行测试,请尝试运行以下命令:</p>
<pre><code>cmd = [sys.executable, 'test_out.py']
</code></pre>
<p>并创建一个包含以下内容的<code>test_out.py</code>文件:</p>
<pre><code>import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
</code></pre>
<p>执行该子流程时,应该给出“Hello”,并在给出“World”之前等待10秒。如果这发生在上面的python代码上,而不是<code>rsync</code>,那就意味着<code>rsync</code>本身正在缓冲输出,所以您运气不好。</p>
<p>一种解决方案是使用类似<code>pexpect</code>的方法直接连接到<code>pty</code>。</p>