2016-08-06 9 views
0

Ich muss Thread beenden, kann aber nicht regelmäßig alle Flags überprüfen, da es auf Lesen/Eingabe wartet.Kill Python Thread, während es lange auf Lesen wartet

Einfaches Beispiel:

import threading, time 

class Test(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 

    def run(self): 
     print(input("wainting for input: ")) 

th = Test() 
th.start() 
time.sleep(5) 
print("killing!") 
th.join(5) 
print(th.is_alive()) 

Das reale Beispiel ist dies (Thread töten, wenn es hängt - keine Ausgabe für längere Zeit):

import threading, time 

class Test(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 

    def call(args): 
     return subprocess.Popen(" ".join(args), shell=True, stderr=subprocess.PIPE)  

    def run(self): 
     mainProcess = call([ any program that could hang]) 
     out = None 
     while mainProcess.returncode != 0 or out == '' and mainProcess.poll() != None: 
      out = mainProcess.stderr.read(1) 
      if out != '': 
       sys.stdout.write(out) 
       sys.stdout.flush() 

th = Test() 
th.start() 
time.sleep(5) 
print("killing!") 
th.join(5) 
print(th.is_alive()) 

Wenn es ein besserer Ansatz ist, würde ich Sei auch glücklich.

+0

es lesen sollte 'subprocess.Popen (args, stderr = subprocess.PIPE)'. 'Call' ist keine Methode. – Daniel

+0

Sie möchten also ein Lese-Timeout? Setzen Sie das Lesen mit einem 'select()' oder 'poll()' mit Timeout voran. – dhke

Antwort

1

Hier ist ein Beispiel, wie Sie Ihr hängenden Prozess Problem mit select lösen können:

import threading 
import select 
import subprocess 
import sys 

def watch_output(args, timeout): 
    process = subprocess.Popen(args, stdout=subprocess.PIPE)  
    while True: 
     ready_to_read, _, _ = select.select([process.stdout], [], [], timeout) 
     if not ready_to_read: 
      print "hanging process" 
      process.kill() 
      break 
     out = ready_to_read[0].read(1) 
     if not out: 
      print "normal exit" 
      break 
     sys.stdout.write(out) 
     sys.stdout.flush() 
    return process.wait() 

watch_output(['ls'], timeout=10) 

oder sogar mit Timeout Ihre Eingabe ist möglich:

def read_input(prompt, timeout): 
    sys.stdout.write(prompt) 
    sys.stdout.flush() 
    ready_to_read, _, _ = select.select([sys.stdin], [], [], timeout) 
    if not ready_to_read: 
     return None 
    return ready_to_read[0].readline() 

print read_input("wainting for input (4s): ", 4) 
+0

nette idee kumpel. – thesonyman101

0

Sie haben nur die Haupt-Thread zu töten der Prozess. Der Leser-Thread wird schließlich EOF treffen und dann beenden.

Beispiel:

#!/usr/bin/env python 

import threading 
import subprocess 
import time 
import sys 

def pipe_thread(handle): 
    print "in pipe_thread" 
    x = handle.readline() 
    while x: 
    print "got:", x[:-1] 
    x = handle.readline() 

def main(): 
    p = subprocess.Popen(["./sender"], stdout = subprocess.PIPE) 
    t = threading.Thread(target = pipe_thread, args = [p.stdout]) 
    t.start() 

    print "sleeping for a while" 
    time.sleep(5) 
    print "killing process" 
    p.kill() 
    print "joining" 
    t.join() 
    print "joined" 

main() 
Verwandte Themen