2011-12-06 12 views
5

मेरे पास संभवतः लंबे समय तक चलने वाला प्रोग्राम है जिसमें वर्तमान में 4 प्रक्रियाएं हैं, लेकिन अधिक होने के लिए कॉन्फ़िगर किया जा सकता है। मैंने पाइथन के logging का उपयोग करके logging from multiple processes पर शोध किया है और here पर चर्चा की गई सॉकेटहैंडलर दृष्टिकोण का उपयोग कर रहा हूं। मुझे कभी भी एक लॉगर (कोई सॉकेट नहीं) होने में कोई समस्या नहीं थी, लेकिन जो मैंने पढ़ा उससे मुझे बताया गया कि यह अंततः और अप्रत्याशित रूप से विफल हो जाएगा। जहां तक ​​मैं इसे अज्ञात समझता हूं, तब भी होगा जब आप एक ही समय में एक ही फाइल को लिखने का प्रयास करेंगे। मेरे कोड अनिवार्य रूप से निम्नलिखित है:एकाधिक प्रक्रियाओं से पाइथन लॉगिंग

import logging 
log = logging.getLogger(__name__) 

def monitor(...): 
    # Spawn child processes with os.fork() 
    # os.wait() and act accordingly 

def main(): 
    log_server_pid = os.fork() 
    if log_server_pid == 0: 
     # Create a LogRecordSocketServer (daemon) 
     ... 
     sys.exit(0) 
    # Add SocketHandler to root logger 
    ... 
    monitor(<configuration stuff>) 

if __name__ == "__main__": 
    main() 

तो मेरी प्रश्न हैं: मैं हर os.fork() के बाद एक नया log वस्तु बनाने की जरूरत है? मौजूदा वैश्विक log ऑब्जेक्ट का क्या होता है?

चीजों को करने के तरीके के साथ, क्या मैं भी उस समस्या के आसपास हो रहा हूं जिसे मैं टालने की कोशिश कर रहा हूं (एकाधिक खुली फ़ाइलें/सॉकेट)? क्या यह असफल हो जाएगा और यह क्यों विफल रहेगा (मैं यह बताना चाहता हूं कि भविष्य में समान कार्यान्वयन विफल हो जाएंगे)?

इसके अलावा, कई प्रक्रियाओं से एक फ़ाइल में लॉगिंग करने की "सामान्य" (एक log= अभिव्यक्ति) विधि किस तरह से विफल हो जाती है? क्या यह IOError/OSError उठाता है? या यह फ़ाइल को पूरी तरह से डेटा नहीं लिखता है?

अगर कोई मेरी मदद करने के लिए उत्तर या लिंक प्रदान कर सकता है, तो यह बहुत अच्छा होगा। धन्यवाद।

FYI करें: मैं पर मैक ओएस एक्स शेर का परीक्षण कर रहा हूँ और कोड शायद एक Windows मशीन पर एक CentOS 6 वी एम पर चल रहा है खत्म हो जाएगा (यदि यह मायने रखती है)। जो भी समाधान मैं उपयोग करता हूं उसे विंडोज पर काम करने की आवश्यकता नहीं है, लेकिन यूनिक्स आधारित सिस्टम पर काम करना चाहिए।

अद्यतन: यह प्रश्न विशिष्ट व्यवहार को लॉगिंग से दूर जाना शुरू कर दिया है और फोर्क के दौरान लिनक्स फ़ाइल डिस्क्रिप्टर के साथ क्या करता है इसके दायरे में अधिक है। मैंने अपनी कॉलेज पाठ्यपुस्तकों में से एक को खींच लिया और ऐसा लगता है कि यदि आप दो प्रक्रियाओं (एक कांटा से पहले नहीं) से एपेंड मोड में एक फ़ाइल खोलते हैं, तो वे दोनों फाइल ठीक से फ़ाइल में लिखने में सक्षम होंगे जब तक कि आपका लेखन अधिक न हो वास्तविक कर्नेल बफर (हालांकि लाइन बफरिंग का उपयोग करने की आवश्यकता हो सकती है, फिर भी उस पर निश्चित नहीं है)। यह 2 फ़ाइल टेबल प्रविष्टियों और एक वी-नोड तालिका प्रविष्टि बनाता है। फ़ाइल खोलना तब फोर्किंग काम नहीं करना चाहिए, लेकिन ऐसा लगता है कि जब तक आप पहले से कर्नेल बफर से अधिक नहीं होते हैं (मैंने इसे पिछले प्रोग्राम में किया है)।

तो मुझे लगता है कि यदि आप मंच स्वतंत्र स्वतंत्र बहु-प्रसंस्करण लॉगिंग चाहते हैं तो आप सॉकेट का उपयोग करें और प्रत्येक कांटा को सुरक्षित रखने के बाद एक नया सॉकेटहैंडलर बनाएं क्योंकि विनय ने नीचे सुझाव दिया है (जो हर जगह काम करना चाहिए)। मेरे लिए, चूंकि मेरे पास ओएस का सॉफ़्टवेयर चल रहा है, इस पर मेरा मजबूत नियंत्रण है, मुझे लगता है कि मैं एक वैश्विक log ऑब्जेक्ट के साथ फाइलहैंडलर के साथ जा रहा हूं (डिफ़ॉल्ट रूप से एपेंड मोड में खुलता है और अधिकांश ओएस पर बफर किया जाता है)। open के लिए प्रलेखन कहता है "एक नकारात्मक बफरिंग का मतलब सिस्टम डिफ़ॉल्ट का उपयोग करना है, जो आम तौर पर टीटीई उपकरणों के लिए लाइन buffered है और अन्य फ़ाइलों के लिए पूरी तरह से buffered है। अगर छोड़ा गया है, तो सिस्टम डिफ़ॉल्ट का उपयोग किया जाता है।" या लाइन बफरिंग सुनिश्चित करने के लिए मैं अपनी खुद की लॉगिंग स्ट्रीम बना सकता हूं। और बस स्पष्ट होना, मैं के साथ ठीक हूँ:

# Process A 
a_file.write("A\n") 
a_file.write("A\n") 
# Process B 
a_file.write("B\n") 

उत्पादन ...

A\n 
B\n 
A\n 

जब तक कि यह उत्पादन नहीं करता है के रूप में ...

AB\n 
\n 
A\n 

विनय (या किसी और), कैसे गलत हूँ? मुझे बताएं। आप जो भी स्पष्टता/सुनिश्चित कर सकते हैं उसके लिए धन्यवाद।

+0

धागे और ताले इस तरह की चीजों के लिए उपयोगी हैं ... –

+0

मुझे अलग प्रक्रियाओं की आवश्यकता है क्योंकि बच्चे बाहरी उपकरणों के साथ संचार कर रहे हैं जो जितना संभव हो सके "त्वरित" होना चाहिए। – daveydave400

+0

मैंने अपना जवाब अपडेट किया। –

उत्तर

2

क्या मुझे प्रत्येक os.fork() के बाद एक नया लॉग ऑब्जेक्ट बनाने की आवश्यकता है? मौजूदा वैश्विक लॉग ऑब्जेक्ट का क्या होता है?

AFAIK वैश्विक लॉग ऑब्जेक्ट माता-पिता और बाल प्रक्रियाओं में एक ही लॉगर को इंगित करता है। तो आपको एक नया निर्माण करने की आवश्यकता नहीं है। हालांकि, मुझे लगता है कि आपको fork()monitor() में SocketHandler के बाद SocketHandler बनाना और जोड़ना चाहिए, ताकि सॉकेट सर्वर में चार अलग-अलग कनेक्शन हों, प्रत्येक बच्चे की प्रक्रिया में से एक। यदि आप ऐसा नहीं करते हैं, तो मॉनिटर() में फोर्क किए गए बच्चे की प्रक्रिया सॉकेटहैंडलर और उसके सॉकेट हैंडल को उनके माता-पिता से प्राप्त होगी, लेकिन मुझे यह सुनिश्चित नहीं है कि यह गलत व्यवहार करेगा। व्यवहार ओएस-निर्भर होने की संभावना है और आप ओएसएक्स पर भाग्यशाली हो सकते हैं।

चीजों को करने के तरीके के साथ, क्या मैं भी उस समस्या के आसपास हो रहा हूं जिसे मैं टालने की कोशिश कर रहा हूं (एकाधिक खुली फ़ाइलें/सॉकेट)? क्या यह असफल हो जाएगा और यह क्यों विफल रहेगा (मैं यह बताना चाहता हूं कि भविष्य में समान कार्यान्वयन विफल हो जाएंगे)?

यदि आप पिछले fork() के रूप में मैं ऊपर सुझाव के बाद सॉकेट सर्वर से सॉकेट कनेक्शन बनाने मैं विफलता की उम्मीद नहीं है, लेकिन मुझे यकीन है कि व्यवहार किसी अन्य मामले में अच्छी तरह से परिभाषित किया गया है नहीं कर रहा हूँ। आप कई खुली फाइलों का संदर्भ लेते हैं लेकिन मुझे आपके छद्म कोड स्निपेट में फ़ाइलों को खोलने का कोई संदर्भ नहीं दिखता है, केवल सॉकेट खोलना।

साथ ही, कई प्रक्रियाओं से एक फ़ाइल में लॉगिंग करने की "सामान्य" (एक लॉग = अभिव्यक्ति) विधि किस तरह से विफल होती है? क्या यह IOError/OSError उठाता है? या यह फ़ाइल को पूरी तरह से डेटा नहीं लिखता है?

मुझे लगता है कि व्यवहार अच्छी तरह से परिभाषित नहीं है, लेकिन कोई विफलता मोड फ़ाइल में विभिन्न प्रक्रियाओं से छेड़छाड़ किए गए लॉग संदेशों के रूप में उपस्थित होने की अपेक्षा करेगा, उदाहरण के लिए

Process A writes first part of its message 
Process B writes its message 
Process A writes second part of its message 

अद्यतन: आप जिस तरह से आप अपनी टिप्पणी में वर्णित में एक FileHandler उपयोग करते हैं, बातें नहीं तो अच्छा, परिदृश्य के लिए मैं ऊपर वर्णित किया है की वजह से हो जाएगा: प्रक्रिया ए और बी दोनों पर इशारा करते हुए शुरू फ़ाइल का अंत (एपेंड मोड की वजह से), लेकिन इसके बाद चीजें सिंक से बाहर हो सकती हैं क्योंकि (उदाहरण के लिए एक मल्टीप्रोसेसर पर, लेकिन यहां तक ​​कि संभावित रूप से एक यूनिप्रोसेसर पर), एक प्रक्रिया पहले (साझा कर सकती है और) साझा फ़ाइल हैंडल को लिख सकती है एक और प्रक्रिया ऐसा करने समाप्त हो गया है।

+0

जब मैंने कई फाइलें कहा तो मेरा मतलब था कि मैंने सॉकेटहैंडलर के बजाय मूल फ़ाइल हैडलर किया था। मैंने एक सहकर्मी से बात की और उन्होंने उल्लेख किया कि यदि लॉगिंग लिनक्स पर एपेंड मोड में एक फ़ाइल हैंडलर खोलती है तो मुझे ठीक होना चाहिए (एक लॉग ऑब्जेक्ट, एक फ़ाइल हैंडलर, एकाधिक कांटेदार)। विचार? और एक कांटा के बाद सॉकेट हैंडलर बनाना समझ में आता है। – daveydave400

+0

मैंने अपना प्रश्न अपडेट किया है, धन्यवाद। – daveydave400

+0

कांटा के बाद सॉकेटहैंडलर के निर्माण के कारण मैं आपका जवाब स्वीकार करूंगा, लेकिन मैं अभी भी एपेंड मोड से असहमत हूं (कर्नेल को एपेंड लिखना चाहिए)। – daveydave400

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