2010-08-11 15 views
7

मेरे पास ऐसा कोड है जो इस तरह कुछ दिखता है:पायथन: एक चर पर ताला के साथ सौदा करने के लिए सुरुचिपूर्ण तरीका?

def startSearching(self): 
    self.searchingLock.acquire() 
    searching = self.searching 
    if self.searching: 
     self.searchingLock.release() 
     self.logger.error("Already searching!") 
     return False 

    self.searching = True 
    self.searchingLock.release() 

    #some more init code, then start the thread which 
    #constantly checks self.searching to determine when to stop 

हालांकि यह बदसूरत है। बहुत सारे अधिग्रहण और रिलीज। यह सुंदर दिखता है:

def startSearching(self): 
    with self.searchingLock: 
     if self.searching: 
      self.logger.error("Already searching!") 
      return False 

     self.searching = True 

    #some more init code, then start the thread which 
    #constantly checks self.searching to determine when to stop 

लेकिन यह लॉक को सख्ती से जरूरी से अधिक रखता है, espcially अगर self.logger.error थोड़ी देर लेता है (जैसे कि यह डिस्क पर लिखता है, जो यह करता है)। लॉक को जितना संभव हो उतना छोटा पकड़ने के बीच कोई मध्य ग्राउंड है लेकिन सुंदर कोड है?

उत्तर

6

हो सकता है कि आप की तरह इस तर्क को अलग करने की आवश्यकता है:

def initSearch(self): 
    with self.searchingLock: 
     if self.searching : raise SearchingError('AlreadySearching') 
     self.searching = True 
def startSearching(self): 
    try: self.initSearch() 
    except SearchingError as error : 
     self.logger.error(error.message) 
     return False 
    #some more init code, then start the thread which 
    #constantly checks self.searching to determine when to stop 

और तुम additionaly अपने searchingLock को इसे स्वचालित रूप से रिलीज़ करने का कारण बताएं।

1

यह आपको एक बचत होगी "self.searchingLock.release()" लगता यह बहुत pythonic या कुछ भी नहीं है, लेकिन यह काम

def startSearching(self): 
    self.searchingLock.acquire() 
    already_searching = self.searching 
    self.searching = True # Since it'll be true in both scenarios 
    self.searchingLock.release() 

    if already_searching: 
     self.logger.error("Already searching!") 

    return not already_searching 
+0

हेएच चालाक =) मुझे यह पसंद है – Claudiu

+0

आप पहले 4 लाइनों को किसी अन्य फ़ंक्शन में आसानी से तोड़ सकते हैं। – user37078

2

कैसे एक कक्षा में चर & ताला लपेटकर के बारे में:

class LockedVariable(object): 
    def __init__(self, value, lock=None): 
     self._value = value 
     self._lock = lock if lock else threading.RLock() 
     self._locked = false: 

    @property 
    def locked(self): 
     return self._locked 

    def assign(self, value): 
     with self: 
      self._value = value 

    def release(): 
     self._locked = False 
     return self._lock.release() 

    def __enter__(self): 
     self._lock.__enter__() 
     self._locked = True 
     return self._value 

    def __exit__(self, *args, **kwargs): 
     if self._locked: 
      self._locked = False 
      return self._lock.__exit__(*args, **kwargs) 

और यह के रूप में उपयोग:

locked_dict = LockedVariable({}) 

with locked_dict as value: 
    value['answer'] = 42 

    if locked_dict.locked: 
     locked_dict.release() 
     print 'eureka! :)' 
     return  

if locked_dict.locked: 
    print 'bahh! :('   

टिप्पणी:

मैं कभी कभी बढ़ावा :: साथ shared_ptr का उपयोग एक ही चीज़ को प्राप्त करने के लिए एक कस्टम डिलीटर, यानी एक अनलॉक वैरिएबल लौटाता है जो इसे बाहर होने पर जारी किया जाता है सामना।

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