2011-07-03 12 views
14

मैं पाइथन के मल्टीप्रोसेसिंग मॉड्यूल के साथ पाइप का उपयोग करके प्रक्रियाओं के बीच सरल वस्तुओं को भेज रहा हूं। दस्तावेज़ीकरण में कहा गया है कि यदि एक पाइप बंद कर दिया गया है, तो pipe.recv() को कॉल करना EOFError को बढ़ाया जाना चाहिए। इसके बजाए, मेरा प्रोग्राम सिर्फ आरईवी() पर अवरुद्ध है और कभी पता नहीं लगाता कि पाइप बंद कर दिया गया है।pipe.clc() पाइथन मल्टीप्रोसेसिंग में pipe.recv() के दौरान EOFError क्यों नहीं करता है?

उदाहरण:

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 

और उत्पादन की तरह दिखता है:

recv: 1 
<blocks here> 

किसी को भी मुझे बता सकते हैं मैं गलत क्या कर रहा हूँ? मुझे लिनक्स और विंडोज/साइगविन पर यह समस्या है, लेकिन विंडोज़ मूल पायथन के साथ नहीं है।

उत्तर

8

फोर्कड (बच्चा) प्रक्रिया अपने माता-पिता के फ़ाइल वर्णनकर्ताओं की प्रति प्राप्त कर रही है। तो हालांकि माता-पिता p1 पर "करीबी" कहते हैं, फिर भी बच्चे की प्रतिलिपि खुली होती है और अंतर्निहित कर्नेल ऑब्जेक्ट जारी नहीं किया जा रहा है।

सुलझाने के लिए आपको बच्चे में पाइप के "लिखने" पक्ष को बंद करने, इसलिए तरह की जरूरत है:

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

(बेशक यह सही है, लेकिन के रूप में यह विंडोज पर करता सवाल का उद्देश्य निर्धारित करने के लिए क्यों पाइप बंद माता-पिता और बच्चे प्रक्रिया के बीच संचार नहीं किया है और जैसा कि दस्तावेज़ीकरण से पता चलता है कि यह होना चाहिए)। – Luke

+1

ठीक है, फिर से जांच करने पर, आप बिल्कुल सही हैं (और मैंने आपके उत्तर को सही ढंग से समझ नहीं लिया)। पाइप को 'बंद' नहीं माना जाता है जब तक कि फ़ाइल डिस्क्रिप्टर का उपयोग करने वाली सभी प्रक्रियाओं ने इसे बंद नहीं किया है। – Luke

+0

इसका एक दिलचस्प/अजीब परिणाम यह है कि पाइप के दोनों सिरों को बाल प्रक्रियाओं में भेजना आवश्यक है ताकि वे स्पष्ट रूप से एक को बंद कर सकें। – Luke

2

this solution से मैं 'पाया है कि os.close(pipe.fileno()) तुरंत पाइप जहां pipe.close को तोड़ सकते थे() तब तक नहीं करता जब तक कि सभी प्रक्रियाओं/उप-प्रक्रियाएं समाप्त न हों। आप इसके बजाए कोशिश कर सकते हैं। चेतावनी: आप पाइप.क्लोज़() के बाद उपयोग नहीं कर सकते हैं, लेकिन पाइप। बंद अभी भी "झूठी" वापस आते हैं। तो अगर आप ऐसा कर सकता है होना करने के लिए क्लीनर:

os.close(pipe.fileno()) 
pipe=open('/dev/null') 
pipe.close() 
संबंधित मुद्दे