2014-08-28 13 views
25

मैं आंशिक फ़ंक्शन का उपयोग करने का प्रयास कर रहा हूं ताकि पूल.मैप() एक ऐसे फ़ंक्शन को लक्षित कर सके जिसमें एक से अधिक पैरामीटर हो (इस मामले में लॉक() ऑब्जेक्ट)।पाइथन प्रक्रियाओं के बीच लॉक साझा करना

Runtime Error: Lock objects should only be shared between processes through inheritance. 

मैं क्या कर रहा हूँ:

from functools import partial 

def target(lock, iterable_item): 
    for item in items: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    l = multiprocessing.Lock() 
    func = partial(target, l) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

लेकिन जब मैं इस कोड चलाने के लिए, मैं त्रुटि मिलती है:

यहां उदाहरण के कोड (एक जवाब से मेरा एक पिछले प्रश्न करने के लिए लिया है) यहाँ याद आ रही है? मैं अपने सबप्रोसेसेस के बीच लॉक कैसे साझा कर सकता हूं?

+0

इस समस्या के बारे में एक और सवाल है, हालांकि उनकी विशेष त्रुटि अलग है - [मल्टीप्रोसेसिंग के साथ लॉक का उपयोग करने में समस्या। पुल: पिकलिंग त्रुटि] (http://stackoverflow.com/questions/17960296/trouble-using-a- लॉक-साथ-मल्टीप्रोसेसिंग-पूल-पिकलिंग-त्रुटि) –

उत्तर

46

क्षमा करें, मुझे इसे आपके अन्य प्रश्न के उत्तर में पकड़ा जाना चाहिए था। आप सामान्य multiprocessing.Lock ऑब्जेक्ट्स को Pool विधियों तक नहीं पारित कर सकते हैं, क्योंकि उन्हें मसालेदार नहीं किया जा सकता है। इसके चारों ओर जाने के दो तरीके हैं। एक Manager() बना सकते हैं और पारित करने के लिए है एक Manager.Lock():

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    m = multiprocessing.Manager() 
    l = m.Lock() 
    func = partial(target, l) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

यह एक छोटा सा दिग्गज, हालांकि है, Manager का उपयोग करके Manager सर्वर होस्ट करने के लिए एक और प्रक्रिया को बढ़ाने की आवश्यकता है। और सभी कॉल acquire/release लॉक को उस सर्वर पर आईपीसी के माध्यम से भेजा जाना है।

दूसरा विकल्प initializer kwarg का उपयोग करके पूल निर्माण समय पर नियमित multiprocessing.Lock() पास करना है। यह अपने लॉक उदाहरण सभी बच्चे कार्यकर्ताओं में वैश्विक कर देगा:

def target(iterable_item): 
    for item in items: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 
def init(l): 
    global lock 
    lock = l 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    l = multiprocessing.Lock() 
    pool = multiprocessing.Pool(initializer=init, initargs=(l,)) 
    pool.map(target, iterable) 
    pool.close() 
    pool.join() 

दूसरा समाधान नहीं रह गया है partial की आवश्यकता के पक्ष प्रभाव है।

+0

ठीक है फिर से धन्यवाद, महोदय। यह बिल्कुल वैसा ही दिखता है जो मुझे चाहिए। वास्तव में निरंतर मदद की सराहना करते हैं! अन्य विकल्प सुपर शामिल देखा। मैं ग्लोबल लॉक साझा करने के लिए प्रारंभकर्ता फ़ंक्शन के साथ जाऊंगा। – DJMcCarthy12

+0

यह बहुत अच्छा काम किया। मैंने प्रत्येक कॉल में गुजरने के लिए इनिट में 'कतार' भी लगाया। – fantabolous

+1

@ डैनो आपके उत्तर के लिए बहुत बहुत धन्यवाद, मेरे पास भी वही प्रश्न था और यह इसे पूरी तरह से हल करता है, हालांकि मेरे पास एक और सवाल है कि इस दृष्टिकोण को प्रबंधक ऑब्जेक्ट के माध्यम से ऐसा करने के बजाय प्रक्रियाओं के बीच राज्य साझा करने के लिए अक्सर क्यों उपयोग नहीं किया जाता है सर्वर प्रक्रियाओं और प्रॉक्सी एक्सेस चलाने का अपना ओवरहेड है? – bawejakunal

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