2013-05-31 38 views
11

Tôi đang khởi chạy một chương trình với subprocess trên Python.Giết một cuộc gọi con đang chạy phụ

Trong một số trường hợp, chương trình có thể bị đóng băng. Điều này nằm ngoài tầm kiểm soát của tôi. Điều duy nhất tôi có thể thực hiện từ dòng lệnh được khởi chạy là CtrlEsc sẽ giết chương trình một cách nhanh chóng.

Có cách nào để mô phỏng điều này với subprocess không? Tôi đang sử dụng subprocess.Popen(cmd, shell=True) để khởi chạy chương trình.

Trả lời

15
p = subprocess.Popen("echo 'foo' && sleep 60 && echo 'bar'", shell=True) 
p.kill() 

Kiểm tra các tài liệu về các mô-đun subprocess để biết thêm: http://docs.python.org/2/library/subprocess.html

+2

Có lẽ nên cố gắng chấm dứt trước khi hoàn toàn tiêu diệt nó. – Gewthen

+1

Đã cố gắng chấm dứt và sau đó giết, subprocess vẫn chạy !! – hungryWolf

+0

có thể là do shell = True –

20

Vâng, có một vài phương pháp trên đối tượng được trả về bởi subprocess.Popen() mà có thể được sử dụng: Popen.terminate()Popen.kill(), mà gửi lần lượt là SIGTERMSIGKILL.

Ví dụ ...

import subprocess 
import time 

process = subprocess.Popen(cmd, shell=True) 
time.sleep(5) 
process.terminate() 

... sẽ chấm dứt quá trình này sau năm giây.

Hoặc bạn có thể sử dụng os.kill() để gửi các tín hiệu khác, như SIGINT để mô phỏng CTRL-C, với ...

import subprocess 
import time 
import os 
import signal 

process = subprocess.Popen(cmd, shell=True) 
time.sleep(5) 
os.kill(process.pid, signal.SIGINT) 
+2

Trên Windows 'kill = terminate' và các tín hiệu không hoạt động theo cùng một cách. – jfs

1

Câu hỏi của bạn không phải là quá rõ ràng, nhưng nếu tôi giả sử rằng bạn đang sắp sửa ra mắt một quá trình đi đến zombie và bạn muốn có thể kiểm soát điều đó trong một số trạng thái kịch bản của bạn. Nếu trường hợp này xảy ra, tôi đề xuất bạn những điều sau:

p = subprocess.Popen([cmd_list], shell=False) 

Điều này không thực sự được khuyến nghị để vượt qua vỏ. Tôi sẽ đề nghị bạn ti sử dụng shell = False, theo cách này bạn có nguy cơ ít bị tràn.

# Get the process id & try to terminate it gracefuly 
pid = p.pid 
p.terminate() 

# Check if the process has really terminated & force kill if not. 
try: 
    os.kill(pid, 0) 
    p.kill() 
    print "Forced kill" 
except OSError, e: 
    print "Terminated gracefully" 
+0

- p.pid là thuộc tính của các cá thể Popen, không phải là phương thức - Khi nào thì OSError được nâng lên? Ngay cả đối với các cuộc gọi Popen đơn giản, (subprocess.Popen ("ls", shell = False)) Tôi dường như không nhận được câu lệnh ngoại trừ. – bergercookie

+0

nó đúng, pid là một tài sản, nó phải là một lỗi đánh máy. Đối với OSError, ngoại lệ được nâng lên ở bước os.kill (pid, 0) nếu pid không tồn tại nữa - p.terminate() đã chấm dứt pid thành công ;-) – ScotchAndSoda

0

Bạn có thể sử dụng hai tín hiệu để giết cuộc gọi phụ đang chạy phụ, tức là signal.SIGTERM và signal.SIGKILL; ví dụ:

import subprocess 
import os 
import signal 
import time 
.. 
process = subprocess.Popen(..) 
.. 
# killing all processes in the group 
os.killpg(process.pid, signal.SIGTERM) 
time.sleep(2) 
if process.poll() is None: # Force kill if process is still alive 
    time.sleep(3) 
    os.killpg(process.pid, signal.SIGKILL) 
Các vấn đề liên quan