2012-10-23 44 views
8

Tôi đang làm việc trên một số tập lệnh (trong công ty tôi làm việc) được tải/dỡ vào trình siêu giám sát để kích hoạt đoạn mã khi sự kiện xảy ra. Cách duy nhất để thực sự tải xuống tập lệnh là nhấn Ctrl - C. Tôi đang viết một hàm bằng Python tự động hóa quy trìnhMô phỏng ngắt bàn phím Ctrl-C trong Python khi đang làm việc trong Linux

Ngay sau khi thấy chuỗi "done" trong đầu ra của chương trình, nó sẽ giết vprobe. Tôi đang sử dụng subprocess.Popen để thực hiện lệnh:

lineList = buff.readlines() 
cmd = "vprobe /vprobe/myhello.emt" 
p = subprocess.Popen(args = cmd, shell=True,stdout = buff, universal_newlines = True,preexec_fn=os.setsid) 
while not re.search("done",lineList[-1]): 
     print "waiting" 
os.kill(p.pid,signal.CTRL_C_EVENT) 

Như bạn thấy, tôi viết ra trong buff mô tả tập tin mở ở chế độ đọc + chế độ ghi. Tôi kiểm tra dòng cuối cùng; nếu nó có 'done', tôi sẽ giết nó. Thật không may, CTRL_C_EVENT chỉ hợp lệ cho Windows. Tôi có thể làm gì cho Linux?

+3

FYI: 're.search' với một chuỗi liên tục có thể được thể hiện tốt hơn là' trong khi 'làm' không lineList [-1]: ... ' – nneonneo

+0

Yup, bạn nói đúng. Cảm ơn. –

Trả lời

8

Tôi nghĩ bạn chỉ có thể gửi tương đương với Linux, signal.SIGINT (tín hiệu ngắt).

(Chỉnh sửa: Tôi từng có điều gì đó ở đây không khuyến khích sử dụng chiến lược này để kiểm soát các quy trình phụ, nhưng đọc kỹ hơn có vẻ như bạn đã quyết định bạn cần control-C trong trường hợp cụ thể này ... SIGINT nên làm điều đó.)

+0

hey Andrew. Cảm ơn câu trả lời. Nhưng trên thực tế, SIGINT chỉ giết chết hàm subprocess trong khi vprobe tiếp tục thực thi nó. Bạn có ý tưởng về cách giết nó không? Cảm ơn –

+1

Vâng, nếu nó hoạt động trên Windows, thì hy vọng điều đó có nghĩa là tín hiệu sẽ đến đúng nơi. Vì vậy, hãy thử một cái gì đó mạnh mẽ hơn. Hãy thử SIGTERM, và nếu nó không hoạt động, SIGKLL. Nếu SIGKILL không hoạt động, thì sẽ không có gì - bạn sẽ phải xem xét các cách khác nhau để xử lý toàn bộ quy trình con. –

+0

Bạn đã thử 'Popen (['vprobe', '/vprobe/myhello.emt'], shell = False, ...)'? @Core_Dumped – alk

1

Có lẽ tôi hiểu nhầm điều gì đó, nhưng cách bạn làm điều đó rất khó để có được kết quả mong muốn.

Bất cứ điều gì buff là, bạn truy vấn nó trước, sau đó sử dụng nó trong ngữ cảnh Popen() và sau đó bạn hy vọng rằng bởi maciv lineList tự lấp đầy.

Những gì bạn có thể muốn là một cái gì đó giống như

logfile = open("mylogfile", "a") 
p = subprocess.Popen(['vprobe', '/vprobe/myhello.emt'], stdout=subprocess.PIPE, buff, universal_newlines=True, preexec_fn=os.setsid) 
for line in p.stdout: 
    logfile.write(line) 
    if re.search("done", line): 
     break 
    print "waiting" 
os.kill(p.pid, signal.CTRL_C_EVENT) 

này mang đến cho bạn một kết thúc ống nuôi dưỡng bởi vprobe kịch bản của bạn mà bạn có thể đọc ra linewise và hành động một cách thích hợp khi đầu ra được tìm thấy.

+0

Đây gần như chính xác những gì tôi muốn làm, ngoại trừ việc tôi muốn đầu ra được in trong một số tệp (cùng với việc đi vào PIPE cho mục đích kiểm tra). Làm thế nào tôi có thể làm điều đó? (Tôi hy vọng tôi đúng ngữ pháp thời gian này :)) –

+0

Tôi đã chỉnh sửa câu trả lời của tôi để cung cấp một cách để làm như vậy. – glglgl

+0

Đoạn mã trên có vẻ tốt và tốt nhưng khi tôi sử dụng stdout như một thuộc tính của đối tượng p, nó mang lại cho tôi lỗi PIPE bị hỏng. –

3

Trong Linux, ngắt bàn phím Ctrl-C có thể được gửi theo lập trình tới một quá trình sử dụng chức năng Popen.send_signal (signal.SIGINT). Ví dụ

import subprocess 
import signal 

.. 
process = subprocess.Popen(..) 
.. 
process.send_signal(signal.SIGINT) 
.. 

Không sử dụng Popen.communicate() cho các lệnh chặn ..

Các vấn đề liên quan