2010-10-06 15 views
6

मुझे एहसास है कि यह Using module 'subprocess' with timeout का डुप्लिकेट हो सकता है। यदि ऐसा है, तो मैं क्षमा चाहता हूं, बस कुछ स्पष्ट करना चाहता था।टाइमआउट एक सबप्रोसेस

मैं एक सबप्रोसेस बना रहा हूं, जिसे मैं निश्चित समय के लिए दौड़ना चाहता हूं, और यदि वह उस समय के भीतर पूरा नहीं होता है, तो मैं इसे एक त्रुटि फेंकना चाहता हूं। क्या निम्न कोड के कामों के साथ कुछ काम करेगा या क्या हमें किसी अन्य प्रश्न में उत्तर जैसे सिग्नल का उपयोग करना होगा? अग्रिम धन्यवाद !:

def run(self): 
    self.runTestCmd() 
    self.waitTestComplete(self.timeout) 

def runTestCmd(self): 
    self.proc = subprocess.Popen("./configure", shell=True) 

def waitTestComplete(self, timeout): 
    st = time.time() 
    while (time.time()-st) < timeout: 
     if self.proc.poll() == 0: 
      return True 
     else: 
      time.sleep(2) 
    raise TestError("timed out waiting for test to complete") 

उत्तर

6

यह होगा, लेकिन इसमें कोई समस्या है। यह प्रक्रिया जारी रखने के बाद भी यह करने के लिए कहा जाता है कि प्रक्रिया करने पर भी यह प्रक्रिया जारी रहेगी। एक बार जब आप इसे छोड़ना चाहते हैं तो आपको इसे छोड़ने के लिए प्रक्रिया को एक सिग्नल भेजना होगा।

चूंकि आप एक नई प्रक्रिया (./configure जो संभवतः एक कॉन्फ़िगर स्क्रिप्ट है) उत्पन्न कर रहे हैं, जो बदले में उप-प्रक्रियाओं का एक पूरा टन बनाता है, यह थोड़ा और जटिल हो जाएगा।

import os 

def runTestCmd(self): 
    self.proc = subprocess.Popen(["./configure"], shell=False, 
           preexec_fn=os.setsid) 

फिर os.kill(-process.pid, signal.SIGKILL) सभी उप-प्रक्रियाओं को बंद कर देना चाहिए। मूल रूप से आप जो कर रहे हैं वह preexec_fn का उपयोग कर रहा है ताकि आपका नया सबप्रोसेस acquire it's own session group हो सके। फिर आप उस सत्र समूह में सभी प्रक्रियाओं के लिए एक संकेत भेज रहे हैं।

कई प्रक्रियाएं जो उपप्रवाहों को जन्म देती हैं, उन्हें पता है कि उन्हें मरने से पहले अपने उपप्रोसेस को साफ करने की आवश्यकता है। इसलिए यदि आप कर सकते हैं तो उनके लिए अच्छा होने का प्रयास करने के लिए यह आपको व्यवहार करता है। पहले os.signal(-process.pid, signal.SIGTERM) आज़माएं, बाहर निकलने की प्रक्रिया के लिए दूसरा या दो प्रतीक्षा करें, फिर SIGKILL आज़माएं। कुछ इस तरह:

import time, os, errno, signal 

def waitTestComplete(self, timeout): 
    st = time.time() 
    while (time.time()-st) < timeout: 
     if self.proc.poll() is not None: # 0 just means successful exit 
      # Only return True if process exited successfully, 
      # otherwise return False. 
      return self.proc.returncode == 0 
     else: 
      time.sleep(2) 
    # The process may exit between the time we check and the 
    # time we send the signal. 
    try: 
     os.kill(-self.proc.pid, signal.SIGTERM) 
    except OSError, e: 
     if e.errno != errno.ESRCH: 
      # If it's not because the process no longer exists, 
      # something weird is wrong. 
      raise 
    time.sleep(1) 
    if self.proc.poll() is None: # Still hasn't exited. 
     try: 
      os.kill(-self.proc.pid, signal.SIGKILL) 
     except OSError, e: 
      if e.errno != errno.ESRCH: 
       raise 
    raise TestError("timed out waiting for test to complete") 

एक तरफ ध्यान दें के रूप में, कभी नहीं, कभी shell=True का उपयोग जब तक आप जानते हैं कि निरपेक्ष कुछ के लिए है कि क्या आप चाहते हैं। गंभीरता से। shell=True कमजोर खतरनाक है और कई सुरक्षा मुद्दों और रहस्यमय व्यवहार का स्रोत है।

+0

आपके उत्तर के लिए धन्यवाद :) मैं पाइथन 2.5 चला रहा हूं, हालांकि इसमें pOpen.kill() नहीं है, और यह सोच रहा था कि मैं उपप्रोसेस को मारने के बारे में कैसे जा सकता हूं। मैंने http://stackoverflow.com/questions/1064335/in-python-2-5-how-do-i-kill-a-subprocess की कोशिश की लेकिन यह काम नहीं लग रहा है। – iman453

+1

@ user388025 - यह वास्तव में आप इसे करने के बारे में कैसे करेंगे। सिवाय इसके कि, यह कॉन्फ़िगर है, है ना? इसका मतलब है कि यह उप-प्रक्रियाओं के एक टन को जन्म देता है, और उनमें से कुछ को मरने में कुछ समय लग सकता है। उस काम को करने के लिए आपको कुछ और जटिल करना पड़ सकता है, इसलिए ये प्रक्रियाएं अपने स्वयं के प्रक्रिया समूह के साथ समाप्त होती हैं। – Omnifarious

+1

@ user388025 - आपका मतलब है '["बनाना", "परीक्षण"] '। कभी भी 'shell = True' का उपयोग न करें जबतक कि आपको बिल्कुल यह पता न हो कि आप किस बारे में हैं। और हां, इससे बहुत से उपप्रवाह भी पैदा होंगे, और मैंने आपके प्रश्न का उत्तर देने के लिए अपना उत्तर संपादित किया। आप 'सिगकिन' के बजाय 'SIGINTR' या 'SIGTERM' संकेतों को भेजने का प्रयास करना भी चाह सकते हैं, इसलिए इसे उप-प्रोसेसिस को साफ़ करने का प्रयास करने का मौका मिलता है। – Omnifarious

संबंधित मुद्दे