<p>您可以安装来自Python 3.2/3.3的<code>subprocess</code>模块的后台端口<a href="http://pypi.python.org/pypi/subprocess32/" rel="nofollow noreferrer">^{<cd1>} module</a><a href="https://stackoverflow.com/a/12698328/4279">mentioned by @gps</a>,以便在2.x上使用。它在Python 2.7上工作,并且包括来自python3.3的超时支持。</p>
<p><a href="https://github.com/python/cpython/blob/03760b0a261dadf317f01ddfbcdf51e73fcfd49c/Lib/subprocess.py#L514-L522" rel="nofollow noreferrer">^{<cd3>} is just ^{<cd4>}</a>因此要在<code>timeout</code>秒内中断长时间运行的进程:</p>
<pre><code>#!/usr/bin/env python
import time
from subprocess import Popen
p = Popen(*call_args)
time.sleep(timeout)
try:
p.kill()
except OSError:
pass # ignore
p.wait()
</code></pre>
<p>如果子进程可能提前结束,则可移植的解决方案是<a href="https://stackoverflow.com/a/10012262/4279">use ^{<cd6>} as suggested in @sussudio's answer</a>:</p>
<pre><code>#!/usr/bin/env python
from subprocess import Popen
from threading import Timer
def kill(p):
try:
p.kill()
except OSError:
pass # ignore
p = Popen(*call_args)
t = Timer(timeout, kill, [p])
t.start()
p.wait()
t.cancel()
</code></pre>
<p>在Unix上,您可以<a href="https://stackoverflow.com/a/1191537/4279">use ^{<cd7>} as suggested in @Alex Martelli's answer</a>:</p>
<pre><code>#!/usr/bin/env python
import signal
from subprocess import Popen
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
signal.signal(signal.SIGALRM, alarm_handler)
p = Popen(*call_args)
signal.alarm(timeout) # raise Alarm in 5 minutes
try:
p.wait()
signal.alarm(0) # reset the alarm
except Alarm:
p.kill()
p.wait()
</code></pre>
<p>为了避免在这里使用线程和信号,Python 3上的<code>subprocess</code>模块使用了<a href="https://github.com/python/cpython/blob/7b2ba5601ae02ec046853a5e468160d443cf24f7/Lib/subprocess.py#L1607-L1653" rel="nofollow noreferrer">busy loop with ^{<cd9>} calls on Unix</a>和<a href="https://github.com/python/cpython/blob/7b2ba5601ae02ec046853a5e468160d443cf24f7/Lib/subprocess.py#L1260-L1275" rel="nofollow noreferrer">^{<cd10>} on Windows</a>。</p>