2012-09-28 33 views
8

Bối cảnh:Tại sao Pexpect không liên tục treo (không phát hiện EOF) sau khi thực hiện các lệnh nhất định?

Tôi có một số mã được viết bằng pexpect, có nhiệm vụ cung cấp cho "sống" đầu ra của một lệnh. I E. in một cái gì đó ra khi một lệnh tạo ra một số đầu ra, hoặc ngay sau đó, thay vì đợi cho đến khi lệnh hoàn thành và sau đó tương tác với đầu ra của nó.

Tất cả những gì tôi đang làm là bắt đầu và dừng dịch vụ. Tôi làm điều này bằng spawn ing quá trình này, và sau đó xuất ra mỗi dòng như nó được in, như vậy:

def watch(process): 
    output = "" 
    while True: 
     try: 
      line = process.read_nonblocking(timeout = -1) 
      print(line, end ="") 
      output += line 
     except pexpect.EOF: 
      break 
    del process 
    return output 

while True: 
    print("IN 1") 
    process = pexpect.spawn("service",["zend-server", "stop"], timeout = None) 
    watch(process) 
    print("OUT 1") 

    print("IN 2") 
    process = pexpect.spawn("service",["zend-server", "start"], timeout = None) 
    watch(process) 
    print("OUT 2") 

Mã này nên chỉ loop dịch vụ: bắt đầu nó và ngăn chặn nó hơn và hơn, in đầu ra của bắt đầu/dừng lại khi nó đi. Nó in đầu ra tốt. Tuy nhiên, nó cuối cùng bị treo ngay trước "OUT 2". Tôi có thể xem đầu ra và xem lệnh gọi service ngừng thực thi. Tuy nhiên, hàm watch không bao giờ tăng EOF và thoát.

Điều này không xảy ra với mọi dịch vụ. Một số dịch vụ lặp vô thời hạn. Tuy nhiên, zend-server, cùng với một vài lệnh không có liên quan khác, không liên tục theo cùng một cách.

Bởi "cuối cùng bị treo", tôi có nghĩa là nó bắt đầu/dừng dịch vụ một vài (biến trên mỗi lần chạy) lần và bị treo. Nó thường nướu răng sau 4-6, mặc dù không bao giờ vào cuộc gọi đầu tiên - luôn luôn ít nhất là trên thứ hai (do đó tuyên bố del; Tôi figured tôi muốn chơi nó an toàn).

Python 2.6.6, CentOS (64) 6.3, Pexpect 2,3-6, FWIW

Câu hỏi:

Tại sao pexpect treo trên lệnh nhất định? Tôi nên giải quyết vấn đề này như thế nào? Sử dụng thời gian chờ không phải là giải pháp khả thi vì một số lệnh này thực sự có thể chạy trong một thời gian dài tùy ý. service zend-server stop chỉ là một trong những tôi đã chọn cho một ví dụ bởi vì nó không mất nhiều thời gian, và tôi có thể quan sát nó hoàn thành.

Những gì tôi đã thử:

tôi đã cố gắng thay thế các phương pháp watch với những điều sau đây, trong đó sử dụng expect('\n'), nhưng kết quả đều giống nhau: một số biến của khởi động lại, và sau đó một treo cuối cùng .

Tôi cũng có thể thêm pexpect.EOF vào mảng là expect ed cùng với \n và xử lý giá trị trả về để thoát ra khỏi vòng lặp, nó vẫn bị treo ở cùng một vị trí.

def watch2(process): 
    output = "" 
    done = False 
    while True: 
     try: 
      if not process.isalive(): 
       line = process.readline() 
       done = True 
      else: 
       process.expect(['\n']) 
       line = process.before 
      print(line) 
      output += line 
      if done: 
       raise pexpect.EOF(0) 
     except pexpect.EOF: 
      break 
    del process 
    return output 
+1

Tại sao bạn sử dụng 'pexpect' khi bạn không làm bất kỳ điều gì tương tác với quy trình con? 'subprocess' từ stdlib sẽ đủ nếu bạn chỉ quan tâm đến đầu ra. –

+1

Đó là một ví dụ đơn giản. Trong phiên bản sản xuất, có các cuộc gọi đến 'mong đợi', nhưng ví dụ bị loại bỏ tôi gửi không hoạt động chính xác. –

+1

Tôi không thể sao chép sự cố của bạn bằng mã này. Tôi không chắc chắn mã là vấn đề.Có lẽ bạn chỉ không nhận được bất kỳ đầu ra từ máy chủ zend? – aychedee

Trả lời

2

Trông giống như vấn đề về đệm khi pexpect đang chờ nhiều dữ liệu hơn. Bạn có thể thử tắt tính năng đệm bằng cách chuyển maxread=1 tới pexpect.spawn()

+0

Không có hiệu lực, nhưng là một ý tưởng hay! –