2010-11-11 13 views
16

मैं जितनी जल्दी हो सके उपप्रोसेस को बार-बार निष्पादित करना चाहता हूं। हालांकि, कभी-कभी प्रक्रिया बहुत अधिक समय लेती है, इसलिए मैं इसे मारना चाहता हूं। मैं नीचे की तरह (...) signal.signal का उपयोग करें:टाइमआउट के दौरान उपप्रोसेसर को मार या समाप्त कर दें?

ppid=pipeexe.pid 
signal.signal(signal.SIGALRM, stop_handler) 

signal.alarm(1) 
..... 
def stop_handler(signal, frame): 
    print 'Stop test'+testdir+'for time out' 
    if(pipeexe.poll()==None and hasattr(signal, "SIGKILL")): 
     os.kill(ppid, signal.SIGKILL) 
     return False 

लेकिन कुछ समय के लिए इस कोड को क्रियान्वित करने से अगले दौर को रोकने की कोशिश करेंगे। /bin/sh:/home/lu/workspace/153/squib_driver के समय के लिए परीक्षण/घर/lu/workspace/152/treefit/test2 रोकें: नहीं मिला --- यह अगला निष्पादन है; कार्यक्रम गलत तरीके से इसे रोकता है।

क्या कोई इसे हल करने के बारे में जानता है? मैं समय में रुकना चाहता हूं समय 1 सेकंड निष्पादित नहीं करना। नींद (एन) अक्सर एन सेकंड प्रतीक्षा करें। मैं नहीं चाहता कि मैं चाहता हूं कि यह 1 सेकंड से कम

+0

तो अनिवार्य रूप से यदि उपप्रोसेस 1 सेकंड से अधिक चलता है, तो आप इसे मारना चाहते हैं और अगले को शुरू करना चाहते हैं? क्या ये सही है? –

+0

आप अपना सबप्रोसेस कैसे बनाते हैं? क्योंकि यह अभिव्यक्ति की तरह दिखता है __ppid = pipeexe.pid__ को अगले उपप्रोसेस मिल रहा है जो चलाया जाएगा !!! – mouad

+0

तो अनिवार्य रूप से यदि उपप्रोसेस 1 सेकंड से अधिक चलाता है, तो आप इसे मारना चाहते हैं और अगला शुरू करना चाहते हैं? क्या ये सही है? हाँ, यह सही है – user504909

उत्तर

35

आप कुछ इस तरह कर सकता है:

import subprocess as sub 
import threading 

class RunCmd(threading.Thread): 
    def __init__(self, cmd, timeout): 
     threading.Thread.__init__(self) 
     self.cmd = cmd 
     self.timeout = timeout 

    def run(self): 
     self.p = sub.Popen(self.cmd) 
     self.p.wait() 

    def Run(self): 
     self.start() 
     self.join(self.timeout) 

     if self.is_alive(): 
      self.p.terminate()  #use self.p.kill() if process needs a kill -9 
      self.join() 

RunCmd(["./someProg", "arg1"], 60).Run() 

विचार यह है कि आप इस मामले 60 सेकंड में एक धागा है कि आदेश चलाता बनाने और इसे मारने के लिए अगर समय समाप्ति कुछ उपयुक्त मूल्य से अधिक है,।

+1

+1। यह विधि मैं निष्पादन योग्य परीक्षण के लिए अपने निर्माण प्रणाली में उपयोग करता हूं। – Macke

+5

भी +1। यह अब तक की सबसे साफ विधियों में से एक प्रतीत होता है। छोटे बदलाव के साथ पाइथन <2.6 पर लिनक्स पर भी os.kill (self.p.pid, सिग्नल। सिगकिल) (या SIGTERM के बाद सिगकिल) का उपयोग कर काम करता है। Self.out, self.err = self.p.communicate() के साथ self.p.wait() को प्रतिस्थापित कर सकते हैं, अगर यह stdout/stderr पाइप को भरता है – FredL

+0

मैंने इस कोड को चिपकाया है और मेरा आदेश इस प्रतीत होता है ठीक से शुरू हो रहा है - हालांकि, मुझे एक समय में एक धागा चलाने की जरूरत है। एक प्रक्रिया शुरू करें, इसे स्वाभाविक रूप से खत्म करें या इसे बहुत लंबे समय तक मार दें, फिर फिर से शुरू करें। –

0

मुझे लगता है कि यह थ्रेड और प्रक्रियाओं के साथ ईवेंट-उन्मुख प्रोग्रामिंग में एक सामान्य सिंक्रनाइज़ेशन समस्या है।

यदि आपके पास हमेशा एक ही उपप्रवाह चलाना चाहिए, तो सुनिश्चित करें कि अगला उपप्रोसेस अगले भाग को चलाने से पहले मारा जाता है। अन्यथा सिग्नल हैंडलर को अंतिम उपप्रोसेस रन का संदर्भ मिल सकता है और पुराने को अनदेखा कर सकता है।

मान लीजिए उपप्रोसेस ए चल रहा है। अलार्म सिग्नल को संभालने से पहले, सबप्रोसेस बी लॉन्च किया गया है। उसके ठीक बाद, आपका अलार्म सिग्नल हैंडलर एक उपप्रजाय को मारने का प्रयास करता है। चूंकि मौजूदा पीआईडी ​​(या वर्तमान उपप्रोसेस पाइप ऑब्जेक्ट) को उपप्रोसेस लॉन्च करते समय बी पर सेट किया गया था, बी को मार दिया गया और ए चल रहा है।

क्या मेरा अनुमान सही है?

अपने कोड को समझने में आसान बनाने के लिए, मैं उस भाग को शामिल करता हूं जो वर्तमान उपप्रोसेस को मारने वाले हिस्से के बाद एक नया उपप्रोसेसर बनाता है। यह स्पष्ट करेगा कि किसी भी समय केवल एक उपप्रोसेस चल रहा है। सिग्नल हैंडलर सबप्रोसेस हत्या और लॉन्चिंग दोनों कर सकता है, जैसे कि यह एक लूप में चलने वाला पुनरावृत्ति ब्लॉक था, इस मामले में हर 1 सेकंड में अलार्म सिग्नल के साथ घटना-संचालित।

2

यहां कुछ ऐसा है जो मैंने सबप्रोसेस निष्पादन के लिए वॉचडॉग के रूप में लिखा था। मैं अब बहुत अधिक उपयोग करते हैं, लेकिन मैं इतना अनुभव नहीं कर रहा हूँ तो शायद इसमें कुछ खामियां हैं:

import subprocess 
import time 

def subprocess_execute(command, time_out=60): 
    """executing the command with a watchdog""" 

    # launching the command 
    c = subprocess.Popen(command) 

    # now waiting for the command to complete 
    t = 0 
    while t < time_out and c.poll() is None: 
     time.sleep(1) # (comment 1) 
     t += 1 

    # there are two possibilities for the while to have stopped: 
    if c.poll() is None: 
     # in the case the process did not complete, we kill it 
     c.terminate() 
     # and fill the return code with some error value 
     returncode = -1 # (comment 2) 

    else:     
     # in the case the process completed normally 
     returncode = c.poll() 

    return returncode 

उपयोग:

return = subprocess_execute(['java', '-jar', 'some.jar']) 

टिप्पणियाँ:

    यहाँ,
  1. वॉचडॉग टाइम आउट सेकेंड में है; लेकिन time.sleep() मान को बदलकर जो भी आवश्यक हो उसे बदलना आसान है। time_out को तदनुसार दस्तावेज करना होगा;
  2. आवश्यकतानुसार, यहां कुछ अपवाद उठाने के लिए यह अधिक उपयुक्त हो सकता है।

प्रलेखन: मुझे यह समझाया गया है कि subprocess.Popen अवरुद्ध नहीं कर रहा है subprocess मॉड्यूल के प्रलेखन के साथ एक सा संघर्ष करना पड़ा; प्रक्रिया समानांतर में निष्पादित की जाती है (शायद मैं यहां सही शब्द का उपयोग नहीं करता, लेकिन मुझे लगता है कि यह समझ में आता है)।

लेकिन जैसा कि मैंने लिखा है, उसके निष्पादन में रैखिक है, मुझे वास्तव में आदेश को पूरा करने की प्रतीक्षा करनी है, ताकि स्क्रिप्ट के रात के निष्पादन को रोकने के लिए कमांड में बग से बचने के लिए समय निकाला जा सके।

0

यहाँ मैं क्या उपयोग है:

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, dir, args, kwargs): 
    event = threading.Event() 
    cwd = os.getcwd() 
    os.chdir(dir) 
    proc = subprocess.Popen(args, **kwargs) 
    os.chdir(cwd) 
    killer = KillerThread(proc.pid, dt, event) 
    killer.start() 

    (stdout, stderr) = proc.communicate() 
    event.set()  

    return (stdout,stderr, proc.returncode) 
0

थोड़ा और अधिक जटिल है, मैं एक answer to solve a similar problem कहा: stdout कैप्चरिंग, stdin खिला, और निष्क्रियता की और/या कुछ समग्र क्रम के बाद कुछ समय के बाद समाप्त करने में सक्षम किया जा रहा है।