2011-07-03 24 views
14

Tôi đang gửi các đối tượng đơn giản giữa các quy trình sử dụng các đường ống với mô-đun đa xử lý của Python. Tài liệu nói rằng nếu một đường ống đã bị đóng, gọi pipe.recv() sẽ tăng EOFError. Thay vào đó, chương trình của tôi chỉ chặn trên recv() và không bao giờ phát hiện rằng đường ống đã bị đóng.Tại sao không pipe.close() gây ra EOFError trong pipe.recv() trong python multiprocessing?

Ví dụ:

import multiprocessing as m 

def fn(pipe): 
    print "recv:", pipe.recv() 
    print "recv:", pipe.recv() 

if __name__ == '__main__': 
    p1, p2 = m.Pipe() 
    pr = m.Process(target=fn, args=(p2,)) 
    pr.start() 

    p1.send(1) 
    p1.close() ## should generate EOFError in remote process 

Và kết quả có dạng:

recv: 1 
<blocks here> 

bất cứ ai có thể cho tôi biết những gì tôi đang làm sai? Tôi có vấn đề này trên Linux và windows/cygwin, nhưng không phải với cửa sổ gốc Python.

Trả lời

8

Quy trình chia nhỏ (con) được kế thừa một bản sao của các bộ mô tả tệp của phụ huynh. Vì vậy, ngay cả khi cha mẹ gọi "đóng" trên p1, đứa trẻ vẫn còn có một bản sao mở và đối tượng hạt nhân cơ bản không được phát hành.

Để khắc phục, bạn cần phải đóng "ghi" bên của ống ở trẻ em, như vậy:

def fn(pipe): 
    p1.close() 
    print "recv:", pipe.recv() 
    print "recv:", pipe.recv() 
+1

Tất nhiên điều này là đúng để xác định lý do tại sao việc đóng ống không được liên lạc giữa quá trình cha và con, như trên Windows (và như các tài liệu cho thấy nó nên). – Luke

+1

Ok, khi kiểm tra lại, bạn hoàn toàn chính xác (và tôi đã không hiểu đúng câu trả lời của bạn). Các đường ống không được coi là 'đóng' cho đến khi tất cả các quá trình bằng cách sử dụng bộ mô tả tập tin đã đóng nó. – Luke

+0

Một kết quả thú vị/vụng về của việc này là cần phải gửi cả hai đầu của đường ống đến các tiến trình con để chúng có thể đóng một cách rõ ràng. – Luke

2

Từ this solution Tôi đã quan sát thấy rằng os.close(pipe.fileno()) ngay lập tức có thể phá vỡ các đường ống nơi pipe.close() không cho đến khi tất cả các tiến trình/tiến trình con kết thúc. Bạn có thể thử thay vào đó. Cảnh báo: Bạn không thể sử dụng pipe.close() sau, nhưng các ảnh tĩnh của đường ống .closed sẽ trả về "false". Vì vậy, bạn có thể làm điều này để được sạch hơn:

os.close(pipe.fileno()) 
pipe=open('/dev/null') 
pipe.close() 
Các vấn đề liên quan