2009-08-31 7 views
15

मुझे पाइथन में निम्न कार्य करने की आवश्यकता है। मैं एक प्रक्रिया (subprocess मॉड्यूल?) उत्पन्न करना चाहता हूं, और:पायथन: एक प्रक्रिया चलाएं और इसे मार दें यदि यह एक घंटे के भीतर समाप्त नहीं होता है

  • यदि प्रक्रिया सामान्य रूप से समाप्त होती है, तो ठीक उसी क्षण से जारी रखने के लिए;
  • यदि अन्यथा, प्रक्रिया "अटक जाती है" और इसे मारने के लिए एक घंटे (कहें) समाप्त नहीं होती है, और इसे जारी रखने के लिए (संभवतः इसे एक और प्रयास देकर, एक लूप में) जारी रखें।

इसे पूरा करने का सबसे शानदार तरीका क्या है?

उत्तर

20

subprocess मॉड्यूल आपका मित्र होगा। Popen ऑब्जेक्ट प्राप्त करने के लिए प्रक्रिया प्रारंभ करें, फिर इसे इस तरह के फ़ंक्शन पर पास करें। ध्यान दें कि यह केवल टाइमआउट पर अपवाद उठाता है। अगर वांछित है तो आप अपवाद को पकड़ सकते हैं और Popen प्रक्रिया पर kill() विधि को कॉल कर सकते हैं। (मार अजगर 2.6 में नया है, btw)

import time 

def wait_timeout(proc, seconds): 
    """Wait for a process to finish, or raise exception after timeout""" 
    start = time.time() 
    end = start + seconds 
    interval = min(seconds/1000.0, .25) 

    while True: 
     result = proc.poll() 
     if result is not None: 
      return result 
     if time.time() >= end: 
      raise RuntimeError("Process timed out") 
     time.sleep(interval) 
8

वहाँ जब तक आप प्रक्रिया पीआईडी ​​पता है psutil का उपयोग करके यह करने के लिए कम से कम 2 तरीके हैं। प्रक्रिया मान लिया जाये कि इस तरह के रूप में बनाया जाता है:

import subprocess 
subp = subprocess.Popen(['progname']) 

... आप इस तरह एक व्यस्त पाश में इसके निर्माण के समय प्राप्त कर सकते हैं:

import psutil, time 

TIMEOUT = 60 * 60 # 1 hour 

p = psutil.Process(subp.pid) 
while 1: 
    if (time.time() - p.create_time) > TIMEOUT: 
     p.kill() 
     raise RuntimeError('timeout') 
    time.sleep(5) 

... या बस, आप यह कर सकते हैं:

import psutil 

p = psutil.Process(subp.pid) 
try 
    p.wait(timeout=60*60) 
except psutil.TimeoutExpired: 
    p.kill() 
    raise 
इसके अलावा

, जब आप यह कर रहे हों, तो आपको निम्न अतिरिक्त API में रुचि हो सकती है:

>>> p.status() 
'running' 
>>> p.is_running() 
True 
>>> 
2

मेरे पास एक ही सवाल था और यह जवाब मिला। अजगर संकेत पुस्तकालय https://docs.python.org/2/library/signal.html

प्रलेखन से::

import signal, os 

def handler(signum, frame): 
    print 'Signal handler called with signal', signum 
    raise IOError("Couldn't open device!") 

# Set the signal handler and a 5-second alarm 
signal.signal(signal.SIGALRM, handler) 
signal.alarm(5) 

# This open() may hang indefinitely 
fd = os.open('/dev/ttyS0', os.O_RDWR) 

signal.alarm(0)   # Disable the alarm 

जब से तुम अंडे देने के लिए करना चाहता था बस पूर्णता के लिए, मैं कैसे समय की एक निश्चित राशि के बाद एक फांसी प्रक्रिया समाप्त करने के लिए एक और रास्ता जोड़ना चाहते हैं वैसे भी एक नई प्रक्रिया, हालांकि यह आपकी समस्या के लिए सबसे अच्छा समाधान नहीं हो सकता है।

1

एक अच्छा, निष्क्रिय, रास्ता थ्रेडिंग का उपयोग करके भी है। टिमर और कॉलबैक फ़ंक्शन सेट अप करना।

from threading import Timer 

# execute the command 
p = subprocess.Popen(command) 

# save the proc object - either if you make this onto class (like the example), or 'p' can be global 
self.p == p 

# config and init timer 
# kill_proc is a callback function which can also be added onto class or simply a global 
t = Timer(seconds, self.kill_proc) 

# start timer 
t.start() 

# wait for the test process to return 
rcode = p.wait() 

t.cancel() 

यदि प्रक्रिया समय पर समाप्त होती है, तो प्रतीक्षा करें() समाप्त होता है और कोड यहां जारी रहता है, रद्द करें() टाइमर को रोकता है। यदि इस बीच टाइमर एक अलग थ्रेड में kill_proc निष्पादित करता है और निष्पादित करता है, तो प्रतीक्षा करें() यहां भी जारी रहेगा और रद्द() कुछ भी नहीं करेगा। आरकोड के मूल्य से आपको पता चलेगा कि हमने टाइमआउट किया है या नहीं। सरलतम kill_proc: (आप निश्चित रूप से वहां कुछ भी अतिरिक्त कर सकते हैं)

def kill_proc(self): 
    os.kill(self.p, signal.SIGTERM)