python - पायथन में एक फाइल लॉकिंग




file-locking (8)

मुझे पायथन में लिखने के लिए फ़ाइल लॉक करने की आवश्यकता है। इसे एक साथ कई पायथन प्रक्रियाओं से एक्सेस किया जाएगा। मुझे ऑनलाइन कुछ समाधान मिल गए हैं, लेकिन अधिकांश मेरे उद्देश्यों के लिए असफल होते हैं क्योंकि वे अक्सर यूनिक्स आधारित या विंडोज आधारित होते हैं।


अन्य समाधान कई बाहरी कोड अड्डों का हवाला देते हैं। यदि आप इसे स्वयं करना पसंद करते हैं, तो यहां क्रॉस-प्लेटफ़ॉर्म समाधान के लिए कुछ कोड है जो लिनक्स / डॉस सिस्टम पर संबंधित फ़ाइल लॉकिंग टूल का उपयोग करता है।

try:
    # Posix based file locking (Linux, Ubuntu, MacOS, etc.)
    import fcntl
    def lock_file(f):
        fcntl.lockf(f, fcntl.LOCK_EX)
    def unlock_file(f): pass
except ModuleNotFoundError:
    # Windows file locking
    import msvcrt
    def file_size(f):
        return os.path.getsize( os.path.realpath(f.name) )
    def lock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_RLCK, file_size(f))
    def unlock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, file_size(f))


# Class for ensuring that all file operations are atomic, treat
# initialization like a standard call to 'open' that happens to be atomic
class AtomicOpen:
    # Open the file with arguments provided by user. Then acquire
    # a lock on that file object (WARNING: Advisory locking)
    def __init__(self, path, *args, **kwargs):
        # Open the file and acquire a lock on the file before operating
        self.file = open(path,*args, **kwargs)
        # Lock the opened file
        lock_file(self.file)

    # Return the opened file object (knowing a lock has been obtained)
    def __enter__(self, *args, **kwargs): return self.file

    # Allows users to use the 'close' function if they want, in case
    # the user did not have the AtomicOpen in a "with" block.
    def close(self): self.__exit__()

    # Unlock the file and close the file object
    def __exit__(self, exc_type=None, exc_value=None, traceback=None):        
        # Release the lock on the file
        unlock_file(self.file)
        self.file.close()
        # Handle exceptions that may have come up during execution, by
        # default any exceptions are raised to the user
        if (exc_type != None): return False
        else:                  return True        

अब, "परमाणु" कथन का उपयोग आमतौर पर "ओपन" कथन का उपयोग करने के लिए किया जा सकता है।

चेतावनी: अगर बाहर निकलने से पहले विंडोज और पायथन क्रैश पर चल रहा है, तो मुझे यकीन नहीं है कि लॉक व्यवहार क्या होगा।

चेतावनी: यहां प्रदान की गई लॉकिंग सलाहकार है, पूर्ण नहीं। सभी संभावित प्रतिस्पर्धी प्रक्रियाओं को "परमाणु ओपन" वर्ग का उपयोग करना चाहिए।


आप pylocker बहुत उपयोगी पा सकते हैं। इसका उपयोग किसी फ़ाइल को लॉक करने या सामान्य रूप से लॉकिंग तंत्र के लिए किया जा सकता है और इसे कई पाइथन प्रक्रियाओं से एक बार में एक्सेस किया जा सकता है।

यदि आप बस एक फ़ाइल लॉक करना चाहते हैं तो यह कैसे काम करता है:

import uuid
from pylocker import Locker

#  create a unique lock pass. This can be any string.
lpass = str(uuid.uuid1())

# create locker instance.
FL = Locker(filePath='myfile.txt', lockPass=lpass, mode='w')

# aquire the lock
with FL as r:
    # get the result
    acquired, code, fd  = r

    # check if aquired.
    if fd is not None:
        print fd
        fd.write("I have succesfuly aquired the lock !")

# no need to release anything or to close the file descriptor, 
# with statement takes care of that. let's print fd and verify that.
print fd

ठीक है, इसलिए मैंने यहां लिखा कोड के साथ जाकर समाप्त किया , मेरी वेबसाइट लिंक मर गई है, archive.org पर देखें ( गिटहब पर भी उपलब्ध है )। मैं इसे निम्नलिखित फैशन में उपयोग कर सकता हूं:

from filelock import FileLock

with FileLock("myfile.txt"):
    # work with the file as it is now locked
    print("Lock acquired.")

फ़ाइल लॉक करना आम तौर पर प्लेटफॉर्म-विशिष्ट ऑपरेशन होता है, इसलिए आपको विभिन्न ऑपरेटिंग सिस्टम पर चलने की संभावना की अनुमति देनी पड़ सकती है। उदाहरण के लिए:

import os

def my_lock(f):
    if os.name == "posix":
        # Unix or OS X specific locking here
    elif os.name == "nt":
        # Windows specific locking here
    else:
        print "Unknown operating system, lock unavailable"

मैं lockfile पसंद करता हूं - प्लेटफ़ॉर्म-स्वतंत्र फ़ाइल लॉकिंग


मैं इस तरह की स्थिति पर काम कर रहा हूं जहां मैं एक ही निर्देशिका / फ़ोल्डर और लॉगिंग त्रुटियों के भीतर से उसी प्रोग्राम की कई प्रतियां चलाता हूं। मेरा दृष्टिकोण लॉग फ़ाइल खोलने से पहले डिस्क पर "लॉक फ़ाइल" लिखना था। कार्यक्रम आगे बढ़ने से पहले "लॉक फ़ाइल" की उपस्थिति के लिए जांच करता है, और "लॉक फ़ाइल" मौजूद होने पर इसकी बारी के लिए प्रतीक्षा करता है।

यहां कोड है:

def errlogger(error):

    while True:
        if not exists('errloglock'):
            lock = open('errloglock', 'w')
            if exists('errorlog'): log = open('errorlog', 'a')
            else: log = open('errorlog', 'w')
            log.write(str(datetime.utcnow())[0:-7] + ' ' + error + '\n')
            log.close()
            remove('errloglock')
            return
        else:
            check = stat('errloglock')
            if time() - check.st_ctime > 0.01: remove('errloglock')
            print('waiting my turn')

संपादित करें --- उपरोक्त बालों के ताले के बारे में कुछ टिप्पणियों पर विचार करने के बाद मैंने "लॉक फ़ाइल" की स्थिरता के लिए एक चेक जोड़ने के लिए कोड संपादित किया। मेरे सिस्टम पर इस समारोह के कई हज़ार पुनरावृत्तियों को समय और 0.002066 का औसत दिया गया ... कुछ सेकंड पहले से:

lock = open('errloglock', 'w')

बस के बाद:

remove('errloglock')

तो मैंने सोचा कि मैं 5 गुणा से शुरू करूँगा जो स्थिरता को इंगित करने और समस्याओं की स्थिति की निगरानी करने के लिए शुरू करेगा।

साथ ही, जब मैं समय के साथ काम कर रहा था, मुझे एहसास हुआ कि मेरे पास थोड़ा सा कोड था जो वास्तव में आवश्यक नहीं था:

lock.close()

जिसे मैंने तुरंत खुले वक्तव्य का पालन किया था, इसलिए मैंने इसे इस संपादन में हटा दिया है।


यहां एक क्रॉस-प्लेटफ़ॉर्म फ़ाइल लॉकिंग मॉड्यूल है: Portalocker

यद्यपि केविन कहते हैं, कई प्रक्रियाओं से एक फ़ाइल में एक बार लिखना कुछ ऐसा है जो आप संभवतः टालना चाहते हैं।

यदि आप डेटाबेस में अपनी समस्या को shoehorn कर सकते हैं, तो आप SQLite का उपयोग कर सकते हैं। यह समवर्ती पहुंच का समर्थन करता है और अपनी लॉकिंग को संभालता है।


लॉकिंग प्लेटफार्म और डिवाइस विशिष्ट है, लेकिन आम तौर पर, आपके पास कुछ विकल्प हैं:

  1. झुंड (), या समकक्ष का उपयोग करें (यदि आपका ओएस इसका समर्थन करता है)। यह सलाहकार लॉकिंग है, जब तक कि आप लॉक की जांच नहीं करते, इसकी अनदेखी की जाती है।
  2. लॉक-कॉपी-मूव-अनलॉक पद्धति का उपयोग करें, जहां आप फ़ाइल की प्रतिलिपि बनाते हैं, नया डेटा लिखें, फिर इसे स्थानांतरित करें (स्थानांतरित करें, कॉपी न करें - चाल लिनक्स में एक परमाणु संचालन है - अपना ओएस जांचें), और आप जांचें लॉक फ़ाइल का अस्तित्व।
  3. एक निर्देशिका को "लॉक" के रूप में उपयोग करें। यह आवश्यक है यदि आप एनएफएस को लिख रहे हैं, क्योंकि एनएफएस झुंड () का समर्थन नहीं करता है।
  4. प्रक्रियाओं के बीच साझा स्मृति का उपयोग करने की भी संभावना है, लेकिन मैंने कभी कोशिश नहीं की है; यह बहुत ओएस-विशिष्ट है।

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

यदि आप क्रॉस प्लेटफ़ॉर्म वाले समाधान की तलाश में हैं, तो आप किसी अन्य तंत्र के माध्यम से किसी अन्य सिस्टम पर लॉगिंग करना बेहतर कर सकते हैं (अगली सबसे अच्छी बात ऊपर एनएफएस तकनीक है)।

ध्यान दें कि एसक्लाइट एनएफएस पर समान बाधाओं के अधीन है जो सामान्य फाइलें हैं, इसलिए आप किसी नेटवर्क शेयर पर SQLite डेटाबेस पर नहीं लिख सकते हैं और मुफ्त में सिंक्रनाइज़ेशन प्राप्त कर सकते हैं।







file-locking