2009-05-16 11 views
10

का उपयोग करके पाइथन प्रोग्राम हाल ही में मुझे एक ऐसी स्क्रिप्ट लिखने की आवश्यकता है जो os.fork() दो प्रक्रियाओं में विभाजित करने के लिए करता है। बाल प्रक्रिया एक सर्वर प्रक्रिया बन जाती है और os.pipe() के साथ बनाए गए पाइप का उपयोग करके मूल प्रक्रिया में वापस डेटा पास करती है। बच्चे पाइप के 'r' के अंत को बंद कर देता है और माता-पिता सामान्य रूप से पाइप के 'w' अंत को बंद कर देता है। मैं os.fdopen के साथ फ़ाइल ऑब्जेक्ट्स में पाइप() से रिटर्न को रूपांतरित करता हूं।os.pipe और os.fork() समस्या

मेरी समस्या यह है कि: यह प्रक्रिया सफलतापूर्वक फोर्क है, और बच्चा सर्वर बन जाता है। सबकुछ बढ़िया काम करता है और बच्चे पाइप के खुले 'w' के अंत में डेटा लिखता है। दुर्भाग्य से पाइप का मूल अंत दो अजीब चीजें करता है:
ए) यह पाइप के 'r' के अंत में read() ऑपरेशन पर अवरुद्ध करता है।
दूसरा, यह पाइप पर रखे गए किसी भी डेटा को पढ़ने में विफल रहता है जब तक कि 'w' अंत पूरी तरह से बंद न हो जाए।

मैंने तुरंत सोचा कि बफरिंग समस्या थी और पाइप.फ्लश() कॉल, लेकिन इससे मदद नहीं मिली।

क्या कोई इस बात पर प्रकाश डाल सकता है कि लेखन अंत तक पूरी तरह से बंद होने तक डेटा क्यों प्रकट नहीं होता है? और क्या read() कॉल करने के लिए कोई रणनीति नहीं है?

यह मेरा पहला पायथन प्रोग्राम है जो फोर्क या इस्तेमाल किए गए पाइप हैं, इसलिए अगर मैंने एक साधारण गलती की है तो मुझे माफ़ कर दो।

+1

आप उपप्रक्रिया मॉड्यूल क्यों उपयोग नहीं कर रहे? –

+0

मैंने सोचा कि सबप्रोसेस मॉड्यूल कमांड का आह्वान करने के लिए था। मैं कोड की दो शाखाओं, एक बच्चे के लिए और माता-पिता के लिए एक के साथ मजबूर कर रहा हूं। – Paradox

+0

क्या आप कुछ कोड पोस्ट कर सकते हैं? –

उत्तर

11

क्या आप आकार निर्दिष्ट किए बिना पढ़ा() का उपयोग कर रहे हैं, या पाइप को एक इटरेटर (for line in f) के रूप में उपयोग कर रहे हैं?यदि ऐसा है, तो शायद यह आपकी समस्या का स्रोत है - पढ़ने() को पढ़ने से पहले फ़ाइल के अंत तक पढ़ने के लिए परिभाषित किया गया है, पढ़ने के लिए जो उपलब्ध है उसे पढ़ने के बजाय। इसका मतलब यह होगा कि जब तक बच्चा बंद नहीं करता तब तक यह अवरुद्ध होगा()।

उदाहरण कोड में लिंक किया गया है, यह ठीक है - माता-पिता अवरुद्ध तरीके से कार्य कर रहे हैं, और केवल अलगाव उद्देश्यों के लिए बच्चे का उपयोग कर रहे हैं। यदि आप जारी रखना चाहते हैं, तो या तो आपके द्वारा पोस्ट किए गए कोड में गैर-अवरुद्ध आईओ का उपयोग करें (लेकिन आधे पूर्ण डेटा से निपटने के लिए तैयार रहें), या भाग में पढ़ें (जैसे r.read (size) या rreadline()) जो तब तक अवरुद्ध होगा जब तक एक विशिष्ट आकार/रेखा पढ़ी नहीं जाती है। (आपको अभी भी बच्चे पर फ्लश कॉल करने की आवश्यकता होगी)

ऐसा लगता है कि पाइप का इलाज एक इटरेटर के रूप में कुछ और बफर का उपयोग कर रहा है, "for line in r:" के लिए आपको जो भी चाहिए वह आपको नहीं दे सकता है यदि आपको प्रत्येक पंक्ति की आवश्यकता है तुरंत उपभोग किया जाएगा। इसे अक्षम करना संभव हो सकता है, लेकिन fdopen में बफर आकार के लिए केवल 0 निर्दिष्ट करना पर्याप्त प्रतीत नहीं होता है।

यहाँ कुछ नमूना कोड है कि काम करना चाहिए:

import os, sys, time 

r,w=os.pipe() 
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0) 

pid = os.fork() 
if pid:   # Parent 
    w.close() 
    while 1: 
     data=r.readline() 
     if not data: break 
     print "parent read: " + data.strip() 
else:   # Child 
    r.close() 
    for i in range(10): 
     print >>w, "line %s" % i 
     w.flush() 
     time.sleep(1) 
+0

अच्छा! साथ ही, '1: ... '' '' के साथ 'iter (r.readline," ") के डेटा को बदलने पर विचार करें:' – mdaoust

-9

पायथन आवेदन में कांटा का "पैरेंट" बनाम "बच्चा" हिस्सा मूर्खतापूर्ण है। यह 16-बिट यूनिक्स दिनों से विरासत है। यह एक दिन से एक प्रभाव है जब कांटा/निष्पादन और निष्पादन महत्वपूर्ण छोटे प्रोसेसर का सबसे महत्वपूर्ण बनाने के लिए महत्वपूर्ण थे।

अपने पायथन कोड को दो अलग-अलग हिस्सों में विभाजित करें: माता-पिता और बच्चे।

मूल भाग को बच्चे भाग को चलाने के लिए subprocess का उपयोग करना चाहिए।

एक कांटा और निष्पादन कहीं वहां हो सकता है - लेकिन आपको परवाह करने की आवश्यकता नहीं है।

+0

"पैरेंट" बनाम "बच्चा" चीज एक उपप्रोसेसर शुरू करने के आवश्यक अर्थशास्त्र का हिस्सा है। एक उपप्रजाय है, और दूसरा नहीं है। –

+0

जबकि सच है कि कांटा माता-पिता और बच्चे को बनाता है, उप-प्रोसेस बनाने के लिए यह आवश्यक नहीं है। ओपन वीएमएस इस तरह से काम नहीं करता है। उप-प्रोसेस मॉड्यूल इस कांटा मालार्की से कहीं अधिक सरल है। –

+2

'फोर्क() 'को विंडोज़ में' CreateProcess()' के बराबर या वीएमएस में समकक्ष के रूप में नहीं सोचें, जो मूल रूप से उपप्रोसेस मॉड्यूल के बाद मॉडलिंग किया जाता है। 'कांटा()' एक नया धागा शुरू करने की तरह है, सिवाय इसके कि धागा में एक अलग प्रक्रिया स्थान होता है (और इसलिए आपको साझा स्मृति के बजाय पाइप के माध्यम से इसके साथ संवाद करने की आवश्यकता है)। 'Subprocess' मॉड्यूल का उपयोग करके आपको प्रक्रिया प्रारंभिकरण (जैसे कि कॉन्फ़िगरेशन फ़ाइलों या कमांड लाइन तर्कों को पार्स करना) के माध्यम से दो बार चलाना होगा, जबकि 'फोर्क()' के साथ आप नहीं करते हैं। इस प्रकार, 'कांटा() 'अधिक कुशल हो सकता है। –

2

Here's बस ऐसा करने के लिए कुछ उदाहरण कोड।

+0

यह वह साइट है जिस पर मैंने मूल रूप से अपना कोड बंद कर दिया था। धन्यवाद – Paradox

5

पढ़ने (लागू करने से पहले

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

का उपयोग करना) दोनों समस्याओं को हल किया। पठन() कॉल अब अवरुद्ध नहीं हो रहा है और लेखन अंत में केवल एक फ्लश() के बाद डेटा दिखाई दे रहा है।

4

मुझे लगता है कि आपने I/o को अवरुद्ध करने और बफरिंग की समस्या हल कर दी है।

यदि आप एक अलग दृष्टिकोण का प्रयास करने का निर्णय लेते हैं तो एक नोट: सबप्रोसेस फोर्क/निष्पादन मुहावरे के बराबर/प्रतिस्थापन है। ऐसा लगता है कि आप ऐसा नहीं कर रहे हैं: आपके पास सिर्फ एक कांटा है (एक निष्पादन नहीं) और दो प्रक्रियाओं के बीच डेटा का आदान-प्रदान - इस मामले में multiprocessing मॉड्यूल (पायथन 2.6+ में) एक बेहतर फिट होगा।

+0

यह मॉड्यूल बहुत रोचक लग रहा है। धन्यवाद, मैं इसे देख लूंगा। – Paradox

+1

+1 'फोर्क() '(ओपी क्या करने की कोशिश कर रहा है) और' फोर्क '/' exec' idiom subprocess मॉड्यूल द्वारा encapsulated के बीच अंतर का उल्लेख करने के लिए +1, जो कुछ पूरी तरह से अलग है। –

संबंधित मुद्दे