2013-08-23 10 views
8

सही समाधान सुनिश्चित करें कि फ़ाइल कई थ्रेड्स और प्रक्रियाओं का उपयोग करते समय कभी नहीं दूषित हो जाएगा क्या है।एक ही फाइल को समवर्ती लेखन और प्रक्रियाओं

सूत्र, जो त्रुटियों को खोलने के बारे में परवाह के लिए संस्करण।

lock = threading.RLock() 
with lock: 
    try: 
    f = open(file, 'a') 
    try: 
     f.write('sth') 
    finally: 
     f.close() # try close in any circumstances if open passed 
    except: 
    pass # when open failed 
प्रक्रियाओं मैं multiprocessing.Lock

का उपयोग करना चाहिए लगता है, लेकिन के लिए

अगर मैं 2 प्रक्रियाओं चाहते हैं, और पहली प्रक्रिया खुद 2 धागे (हर एक प्रयोग फाइल)

सिर्फ सिद्धांत है, लेकिन मैं जानता हूं कि थ्रेड और प्रक्रियाओं के साथ सिंक्रनाइज़ेशन कैसे मिलाएं। धागे प्रक्रिया से "उत्तराधिकारी" हैं ?, इसलिए केवल प्रक्रियाओं के बीच सिंकोननाइज़ेशन आवश्यक है?

और 2. मुझे यकीन है कि इसके बाद के संस्करण कोड के मामले में जरूरत नेस्टेड कोशिश जब लिखने असफल हो जायेगी अगर नहीं कर रहा हूँ, और हम पास फ़ाइल

+0

एक तरफ ध्यान दें के रूप में, अपने 'try' /' finally' (और आमतौर पर होना चाहिए) एक 'with' बयान के साथ बदला जा सकता है। इसके अलावा, 'छोड़कर: पास' आमतौर पर एक बुरा विचार है-यदि आप किसी विशेष अपवाद को निगलने की कोशिश कर रहे हैं, तो बस उस विशेष को निगलें, सब कुछ नहीं। यदि आप यहां चारों ओर देखते हैं, तो आपको उन लोगों के दर्जनों प्रश्न मिलेंगे जिनके पास मूर्खतापूर्ण त्रुटियां थीं, जैसे एक फ़ाइल नाम के रूप में एक इंट पास करना, जो उन्हें छोड़कर और ध्यान देने से रोकता था। – abarnert

+0

इसके अलावा, यदि आप विशेष रूप से फ़ाइलों के लिए लॉक कर रहे हैं, तो आप पीओएसईक्स पर सलाहकार फ़ाइल ताले का उपयोग करने और जेनेरिक थ्रेड/प्रोसेस लॉक के बजाय विंडोज़ पर विशेष फ़ाइल एक्सेस पर विचार करना चाह सकते हैं। – abarnert

+1

एक और संभावना है कि एक ही थ्रेड (एक ही प्रक्रिया में) से जुड़ी सभी फाइलें करें, और हर कोई सिर्फ एक कतार में संदेश पोस्ट करे (जिसे किसी भी सिंक्रनाइज़ेशन की आवश्यकता नहीं है, क्योंकि यह निर्मित है)। – abarnert

उत्तर

7

इस isn '(यदि यह जारी किया गया ताला के बाद खोला रहेगा क्या) खोलना चाहते हैं टी the docs से पूरी तरह से स्पष्ट नहीं है, मल्टीप्रोसेसिंग सिंक्रनाइज़ेशन प्राइमेटिव वास्तव में धागे को सिंक्रनाइज़ करते हैं।

उदाहरण के लिए, अगर आप इस कोड चलाएँ:

import multiprocessing 
import sys 
import threading 
import time 

lock = multiprocessing.Lock() 

def f(i): 
    with lock: 
     for _ in range(10): 
      sys.stderr.write(i) 
      time.sleep(1) 

t1 = threading.Thread(target=f, args=['1']) 
t2 = threading.Thread(target=f, args=['2']) 
t1.start() 
t2.start() 
t1.join() 
t2.join() 

... उत्पादन हमेशा 1111111111222222222 या 22222222221111111111, दो की नहीं एक मिश्रण होगा।

ताले विंडोज पर Win32 गिरी समन्वयन ऑब्जेक्ट के शीर्ष पर लागू किया जाता है, POSIX प्लेटफार्मों पर संकेतबाहु है कि उन्हें समर्थन है, और वे बिल्कुल ही नहीं अन्य प्लेटफार्मों पर लागू। (आप import multiprocessing.semaphore के साथ इस परीक्षण कर सकते हैं, के रूप में किए गए दस्तावेज़ों में विस्तार से बताया है जो अन्य प्लेटफार्मों पर एक ImportError बढ़ा देंगे।)


कहा जा रहा है, यह निश्चित रूप से सुरक्षित है ताले के दो स्तर के लिए, जब तक कि आप हमेशा उन्हें सही क्रम-कि है में उपयोग करते हैं, threading.Lock हड़पने कभी नहीं जब तक आप सुनिश्चित कर सकते हैं कि आपके प्रक्रिया multiprocessing.Lock है।

आप इस चतुराई से काफी करते हैं, यह प्रदर्शन लाभ हो सकता है। (Windows पर क्रॉस-प्रोसेस ताले, और कुछ POSIX प्लेटफार्मों पर, परिमाण इंट्रा-प्रक्रिया ताले की तुलना में धीमी के आदेश हो सकता है।)

तुम सिर्फ स्पष्ट तरीके से करते हैं (केवल with threadlock:with processlock: अंदर ब्लॉक करते हैं), यह स्पष्ट रूप से प्रदर्शन में मदद नहीं करेगा, और वास्तव में चीजों को धीमा कर देगा (हालांकि काफी संभवतः मापने के लिए पर्याप्त नहीं है), और इससे कोई प्रत्यक्ष लाभ नहीं मिलेगा। बेशक आपके पाठकों को पता चलेगा कि आपका कोड सही है, भले ही उन्हें पता न हो कि multiprocessing ताले धागे के बीच काम करते हैं, और कुछ मामलों में इंट्राप्रोसेस डेडलॉक्स डीबगिंग इंटरप्रोसेस डेडलॉक्स डीबग करने से बहुत आसान हो सकता है ... लेकिन मुझे लगता है कि इनमें से कोई भी नहीं ज्यादातर मामलों में अतिरिक्त जटिलता के लिए यह एक अच्छा कारण है।

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