2016-08-06 62 views
5

Potrzeba:Jak uruchomić proces z limitu czasu i wciąż stdout przy starcie

  1. Timeout po X sekund, a zabić proces (i wszystkie procesy on otwarty), jeśli limit czasu osiągnął przed zakończeniem procesu wdzięcznie .
  2. Odczytywanie bieżących wyników w czasie wykonywania.
  3. Pracuj z procesami, które produkują dane wyjściowe, które nie wytwarzają danych wyjściowych, a następnie przestań je produkować (np. Zablokuj ).
  4. Uruchom w systemie Windows.
  5. Uruchom na Pythonie 3.5.2.

Moduł podprocesu Python 3 ma timeout wbudowany, a także próbowałem i zaimplementowałem timeout sam używając timera i używając wątków, ale nie działa z wyjściem. readline() blokuje się czy nie? readlines() zdecydowanie czeka na zakończenie procesu, zanim wyplunie wszystkie dane wyjściowe, co nie jest tym, czego potrzebuję (potrzebuję w toku).

Jestem blisko przełączania node.js :-(

+2

Problem ze stdout może dotyczyć procesu potomnego. Jeśli bufor standardowy nie zostanie przepłukany, python nigdy nie odbierze zawartości (i będzie to taki sam język, jakiego używałeś). Jednym możliwym rozwiązaniem (nieprzetestowanym) byłoby "podproces.popen", aby przypisać standardowe wyjście dziecka do stderr. Zwykle stderr jest niebuforowany. – cdarke

+1

Tak, 'readline' będzie blokował, czekając na odebranie następnego wiersza, podobnie jak cokolwiek innego, co czyta' sys.stdin'. Możesz powiedzieć Pythonowi, aby 'sys.stdout' był niebuforowany przez podanie opcji' -u' w wierszu poleceń. –

+6

Nikt się nie przejmuje, jeśli przełączysz się na node.js ... – martineau

Odpowiedz

4

użyłbym asyncio dla tego rodzaju zadania

Czytaj IO z procesu jak w tym przyjętym anwser. How to stream stdout/stderr from a child process using asyncio, and obtain its exit code after?

(nie chcę, aby w pełni skopiować go tutaj)

owinąć go w timeout:

async def killer(trans, timeout): 
    await asyncio.sleep(timeout) 
    trans.kill() 
    print ('killed!!') 

trans, *other_stuff = loop.run_until_complete(
          loop.subprocess_exec(
           SubprocessProtocol, 'py', '-3', '-c', 'import time; time.sleep(6); print("Yay!")' , 
             ) 
         ) 

asyncio.ensure_future(killer(trans, 5)) # 5 seconds timeout for the kill 
loop.run_forever() 

Miłej zabawy ...

+0

Niestety, nie udało mi się przerwać procesu po 5 sekundach, o których wspomniałeś. –

+0

@NaphtaliGilead - Proces nie ma limitu czasu, ale twoje połączenie powróci, a następnie możesz go zabić –

+0

Zaktualizowano, aby zabić proces po 5 sekundach –

0

Użyj poniższego 2 skryptu python.

  • Master.py użyje Popen rozpocząć nowy proces i rozpocznie gwint watcher które zabicia procesu po 3.0 sekund.

  • Niewolnik musi wywołać metodę płukania jeśli nie nowej linii w danych zapisanych do stdout (na oknami '\n' również spowodować przypływ).

Uważać moduł time nie jest wysoka precyzja czasomierza.

Czas ładowania procesu może być dłuższy niż 3,0 sekundy, w ekstremalnych przypadkach (odczytu pliku wykonywalnego z pamięci USB typu flash o 1.0)

Master.py

import subprocess, threading, time 

def watcher(proc, delay): 
    time.sleep(delay) 
    proc.kill() 

proc = subprocess.Popen('python Slave.py', stdout = subprocess.PIPE) 
threading.Thread(target = watcher, args = (proc, 3.0)).start() 

data = bytearray() 

while proc: 
    chunk = proc.stdout.read(1) 
    if not chunk: 
     break 
    data.extend(chunk) 
    print(data) 

Niewolnik.py

import time, sys 

while True: 
    time.sleep(0.1) 
    sys.stdout.write('aaaa') 
    sys.stdout.flush() 
+0

Twój przykład działa, ale nie mogę uruchomić procesu i uzyskać danych wyjściowych. –

+0

użyj pełnej ścieżki do pliku wykonywalnego. przykład: 'c: \ windows \ system32 \ py.exe'' d: \ Slave.py' –