Voici comment je le fais ... il utilise un sous-processus donc vous aurez besoin de le modifier pour utiliser popen.
class KillerThread(threading.Thread):
def __init__(self, pid, timeout, event):
threading.Thread.__init__(self)
self.pid = pid
self.timeout = timeout
self.event = event
self.setDaemon(True)
def run(self):
self.event.wait(self.timeout)
if not self.event.isSet() :
try:
os.kill(self.pid, signal.SIGKILL)
except OSError, e:
#This is raised if the process has already completed
pass
def runTimed(dt, args, kwargs):
event = threading.Event()
proc = subprocess.Popen(args, **kwargs)
killer = KillerThread(proc.pid, dt, event)
killer.start()
(stdout, stderr) = proc.communicate()
event.set()
return (stdout,stderr, proc.returncode)
#EXAMPLE USAGE - lets it run for at most 3 seconds
(stdout, stderr, returncode) = \
runTimed(3, \
["path/to/my/executable", "arg1" ] , \
{'stdout':subprocess.PIPE, 'stderr':subprocess.PIPE})
Vous pouvez probablement éviter la nécessité d'un fil supplémentaire si vous utilisez stderr, stdout directement plutôt que d'utiliser communiquer, vous auriez juste besoin de faire attention à utiliser IO non-blocage sur les poignées.
Voilà comment je l'ai fait - en utilisant le filetage dans .NET –