2012-06-27 23 views
7

निम्नलिखित कार्यक्रम:मैं multiprocessing.Pool में operator.itemgetter का उपयोग क्यों नहीं कर सकता?

import multiprocessing,operator 
f = operator.itemgetter(0) 
# def f(*a): return operator.itemgetter(0)(*a) 
if __name__ == '__main__': 
    multiprocessing.Pool(1).map(f, ["ab"]) 

निम्नलिखित त्रुटि के साथ विफल:

Process PoolWorker-1: 
Traceback (most recent call last): 
    File "/usr/lib/python3.2/multiprocessing/process.py", line 267, in _bootstrap 
    self.run() 
    File "/usr/lib/python3.2/multiprocessing/process.py", line 116, in run 
    self._target(*self._args, **self._kwargs) 
    File "/usr/lib/python3.2/multiprocessing/pool.py", line 102, in worker 
    task = get() 
    File "/usr/lib/python3.2/multiprocessing/queues.py", line 382, in get 
    return recv() 
TypeError: itemgetter expected 1 arguments, got 0 

क्यों मैं त्रुटि (CPython 2.7 और 3.2 पर लिनक्स x64 पर) मिलता है, और क्यों यह गायब पड़ता अगर मैं तीसरी पंक्ति को अपूर्ण करें?

उत्तर

6

समस्या है कि यहाँ बहु मॉड्यूल अन्य प्रक्रियाओं (जाहिर है) में प्रतिलिपि द्वारा वस्तुओं गुजरता है, और itemgetter वस्तुओं का उपयोग कर स्पष्ट साधन के किसी भी copyable नहीं हैं:

In [10]: a = operator.itemgetter(0) 
Out[10]: copy.copy(a) 
TypeError: itemgetter expected 1 arguments, got 0 

In [10]: a = operator.itemgetter(0) 
Out[10]: copy.deepcopy(a) 
TypeError: itemgetter expected 1 arguments, got 0 

In [10]: a = operator.itemgetter(0) 
Out[10]: pickle.dumps(a) 
TypeError: can't pickle itemgetter objects 

# etc. 
समस्या

भी नहीं है अन्य प्रक्रियाओं के अंदर एफ कॉल करने का प्रयास; यह इसे पहली जगह कॉपी करने की कोशिश कर रहा है। (यदि आप ऊपर दिए गए स्टैक निशान को देखते हैं, तो आपको यह विफल होने पर बहुत अधिक जानकारी दिखाई देगी।)

बेशक आमतौर पर इससे कोई फर्क नहीं पड़ता, क्योंकि यह लगभग आसान और कुशल है एक कॉपी करने के लिए फ्लाई पर एक नया itemgetter। और यह वही है जो आपका वैकल्पिक "एफ" फ़ंक्शन कर रहा है। (फ्लाई पर एक आइटमजेटर बनाने वाले फ़ंक्शन की प्रतिलिपि करने के लिए निश्चित रूप से आइटम आइटम को कॉपी करने की आवश्यकता नहीं होती है।)

आप "एफ" को लैम्ब्डा में बदल सकते हैं। या एक मामूली फ़ंक्शन (नाम या लैम्ब्डा) लिखें जो आइटमजटर का उपयोग किये बिना वही काम करता है। या एक आइटमजटर प्रतिस्थापन लिखें जो प्रतिलिपि योग्य है (जो स्पष्ट रूप से इतना कठिन नहीं होगा)। लेकिन आप सीधे आइटमगेटर ऑब्जेक्ट्स का उपयोग नहीं कर सकते-जैसा आप चाहते हैं।

+0

वाह, मैंने वास्तव में आपके उत्तर से कुछ सीखा। +1 और धन्यवाद। – steveha

+1

वैसे, यदि आप सोच रहे हैं, तो वास्तविक कारण क्यों आइटमजटर की प्रतिलिपि नहीं बनाई जा सकती है (और तुलना नहीं की जा सकती है, इसे धोया नहीं जा सकता है, स्पष्ट उपयोगी repr, आदि नहीं है) isn ' इतने ज्यादा नहीं कि किसी ने सोचा कि ऑपरेटर.c में उन सभी को लागू करना एक बुरा विचार होगा, क्योंकि कोई भी नहीं सोचा था कि यह लागू करने के लायक होने के लिए पर्याप्त महत्वपूर्ण था। इसके बारे में एक अजगर-देव या पायथन-विचार धागा है। – abarnert

+1

ध्यान दें कि यह लैम्ब्डा के साथ भी विफल रहता है, लेकिन अधिक समझदार 'पिकलिंग एरर: अचार नहीं कर सकता : विशेषता लुकअप __builtin __। फ़ंक्शन विफल'। – phihag