2010-10-27 13 views
6

Tôi muốn sử dụng tiến trình con để chạy chương trình, nhưng tôi cần giới hạn thời gian thực hiện. Ví dụ, nếu nó chạy hơn 2 giây, tôi muốn giết nó.Làm thế nào để hạn chế thời gian thực hiện của chương trình khi sử dụng tiến trình con?

Đối với các chương trình phổ biến, lệnh kill() hoạt động tốt. Nhưng nếu tôi cố gắng chạy /usr/bin/time something, kill() không thể thực sự giết chương trình.

Nhưng mã của tôi dưới đây có vẻ không hoạt động tốt, chương trình vẫn đang chạy.

import subprocess 
import time 

exec_proc = subprocess.Popen("/usr/bin/time -f \"%e\\n%M\" ./son > /dev/null", stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell = True) 

max_time = 1 
cur_time = 0.0 
return_code = 0 
while cur_time <= max_time: 
    if exec_proc.poll() != None: 
     return_code = exec_proc.poll() 
     break 
    time.sleep(0.1) 
    cur_time += 0.1 

if cur_time > max_time: 
    exec_proc.kill() 
+0

nhân đôi với http://stackoverflow.com/questions/1191374/subprocess-with-timeout – starrify

Trả lời

3

làm điều đó như vậy trong dòng lệnh của bạn:

perl -e 'alarm shift @ARGV; exec @ARGV' <timeout> <your_command> 

này sẽ chạy lệnh <your_command> và chấm dứt nó trong <timeout> thứ hai.

một ví dụ giả:

# set time out to 5, so that the command will be killed after 5 second 
command = ['perl', '-e', "'alarm shift @ARGV; exec @ARGV'", "5"] 

command += ["ping", "www.google.com"] 

exec_proc = subprocess.Popen(command) 

hoặc bạn có thể sử dụng signal.alarm() nếu bạn muốn nó với python nhưng đó là cùng.

+6

Trả lời một câu hỏi Python với Perl, đẹp ... –

+0

Nó hoạt động tốt, nhưng khi tôi cố gắng "perl -e 'báo động shift @ARGV; exec @ARGV '3/usr/bin/time ping google.com ", chương trình sẽ không dừng lại. –

+0

Vậy làm cách nào để xử lý/usr/bin/time some_command? –

9

Nếu bạn đang sử dụng Python 2.6 trở lên, bạn có thể sử dụng mô-đun multiprocessing.

from multiprocessing import Process 

def f(): 
    # Stuff to run your process here 

p = Process(target=f) 
p.start() 
p.join(timeout) 
if p.is_alive(): 
    p.terminate() 

Trên thực tế, đa là module sai cho nhiệm vụ này kể từ khi nó chỉ là một cách để kiểm soát bao lâu a thread chạy. Bạn không có quyền kiểm soát đối với bất kỳ trẻ em mà luồng có thể chạy. Như kỳ dị cho thấy, sử dụng signal.alarm là cách tiếp cận bình thường.

import signal 
import subprocess 

def handle_alarm(signum, frame): 
    # If the alarm is triggered, we're still in the exec_proc.communicate() 
    # call, so use exec_proc.kill() to end the process. 
    frame.f_locals['self'].kill() 

max_time = ... 
stdout = stderr = None 
signal.signal(signal.SIGALRM, handle_alarm) 
exec_proc = subprocess.Popen(['time', 'ping', '-c', '5', 'google.com'], 
          stdin=None, stdout=subprocess.PIPE, 
          stderr=subprocess.STDOUT) 
signal.alarm(max_time) 
try: 
    (stdout, stderr) = exec_proc.communicate() 
except IOError: 
    # process was killed due to exceeding the alarm 
finally: 
    signal.alarm(0) 
# do stuff with stdout/stderr if they're not None 
+0

Cảm ơn, nhưng nó không hoạt động: < –

+0

# Hãy thử. Sau 3 giây, ping vẫn đang chạy. nhập khẩu subprocess thời gian nhập khẩu từ đa xử Process nhập khẩu def f(): exec_proc = subprocess.Popen ("/ usr/bin/thời gian ping google.com", shell = True) p = Process (mục tiêu = f) p.start() p.join (3) nếu p.is_alive(): p.terminate() time.sleep (10) –

+0

Bạn nói đúng. 'p.terminate()' chỉ giết chết luồng, không phải bất kỳ con nào được sinh ra. Tôi không thấy lý do tại sao bạn đang sử dụng 'shell = True' vì vậy tôi sẽ cập nhật câu trả lời của tôi với một giải pháp sử dụng signal.alarm như singularity cho thấy. – jamessan

0

Tôi sử dụng os.kill() nhưng không chắc chắn nếu nó hoạt động trên tất cả các hệ điều hành.
Mã giả sau và xem trang của Doug Hellman.

proc = subprocess.Popen(['google-chrome'])            
os.kill(proc.pid, signal.SIGUSR1)</code>