2011-11-14 13 views
5

के रूप में नहीं मिला है, मुझे एक समस्या आई है जिसे मैं हल नहीं कर सकता और यह मल्टीप्रोसेसिंग से जुड़ा हुआ है और इसे सजावटी के अंदर उपयोग करता है।सजावट के अंदर मल्टीप्रोसेसिंग का उपयोग त्रुटि उत्पन्न करता है: फ़ंक्शन फ़ंक्शन नहीं कर सकता ... यह

जब मैं विधि run_in_parallels बहु मैं हूँ त्रुटि मिल रही है का उपयोग कर फोन कर रहा हूँ:

Can't pickle <function run_testcase at 0x00000000027789C8>: it's not found as __main__.run_testcase

कॉल डेकोरेटर के अंदर जगह लेता है, तो उपर्युक्त समस्या का पालन किया। उसी विधि को कॉल करने के समय run_in_parallels बिना सजावट के सभी ठीक से काम कर रहे हैं।

इस समस्या का कारण क्या है?


फ़ाइल: w_PythonHelper.py

desc: समारोह 'run_in_parallel' एक साथ कई प्रक्रियाओं को चलाने के लिए प्रयोग किया जाता है। पहला तरीका, जो ऑपरेशन समाप्त करेगा, दूसरों को रोक देता है।

from multiprocessing import Process,Event 

class ExtProcess(Process): 
    def __init__(self, event,*args,**kwargs): 
     self.event=event 
     Process.__init__(self,*args,**kwargs) 

    def run(self): 
     Process.run(self) 
     self.event.set() 

class PythonHelper(object): 
    @staticmethod 
    def run_in_parallel(*functions): 
     event=Event() 
     processes=dict() 
     for function in functions: 
      fname=function[0] 
      try:fargs=function[1] 
      except:fargs=list() 
      try:fproc=function[2] 
      except:fproc=1 
      for i in range(fproc): 
       process=ExtProcess(event,target=fname,args=fargs) 
       process.start() 
       processes[process.pid]=process 
     event.wait() 
     for process in processes.values(): 
      process.terminate() 
     for process in processes.values(): 
      process.join() 

फ़ाइल: w_Recorder.py

desc: समारोह 'कब्जा' एक स्क्रीनशॉट हड़पने के लिए प्रयोग किया जाता है

from PIL import ImageGrab 
import time 

class Recorder(object): 
    def capture(self): 
     ImageGrab.grab().save("{f}.{e}".format(f=time.time(),e="png")) 

फ़ाइल: w_Decorators.py

desc: रनिंग वर्ग की एक विधि 'कब्जा' के साथ-साथ किसी दिए गए समारोह समानांतर 'रिकॉर्डर'

from w_Recorder import Recorder 
from w_PythonHelper import PythonHelper 

def check(function): 
    def wrapper(*args): 
     try: 
      recorder=Recorder() 
      PythonHelper.run_in_parallel([function,args],[recorder.capture]) 
      print("success") 
     except Exception as e: 
      print("failure: {}".format(e)) 
     return function 
    return wrapper 

फ़ाइल: w_Logger.py

desc: मुख्य कार्यक्रम (उत्पन्न त्रुटि)

from w_Decorators import check 
import time 

class Logger(object): 

    @check 
    def run_testcase(self): 
     # example function (runtime: 20s) 
     for i in range(20): 
      print("number: {}".format(i)) 
      time.sleep(1) 

    def run_logger(self): 
     self.run_testcase() 


if __name__=="__main__": 
    logger=Logger() 
    logger.run_logger() 

फ़ाइल: w_Logger.py

desc: मुख्य कार्यक्रम (corectly काम करता है)

from w_PythonHelper import PythonHelper 
from w_Recorder import Recorder 
import time 

class Logger(object): 

    def run_testcase(self): 
     # example function (runtime: 20s) 
     for i in range(20): 
      print("number: {}".format(i)) 
      time.sleep(1) 

    def run_logger(self): 
     recorder=Recorder() 
     PythonHelper.run_in_parallel([self.run_testcase],[recorder.capture]) 

if __name__=="__main__": 
    logger=Logger() 
    logger.run_logger() 

अंतर यह है कि ये वही दो मामलों में प्रस्तुत तरीकों अलग तरह से काम क्या है?


संपादित करें: किसी को भी इस समस्या को (इस अजगर बग है) को हल करने के एक विचार है करता है? यदि नहीं, तो हो सकता है कि एप्लिकेशन चलने पर स्क्रीन शॉट्स को कैप्चर करने का कोई अच्छा तरीका हो?multiprocessing.Process subclass works on Linux but not Windows

जवाब है::

असल में मैं समान प्रश्न पाया To fix this, you can remove the process member., लेकिन मैं कैसे मेरे उदाहरण के लिए ऐसा कर सकते हैं।

त्रुटि डिबगिंग घटती है जब में run_in_parallel(*functions)


EDIT2 process.start() बुला: तरह ivan_pozdeev ने लिखा है: मैं एक समारोह के रूप आवरण का उपयोग कर सकते हैं, लेकिन डेकोरेटर के रूप में उपयोग नहीं कर सकते। मेरे पास इस सजावट द्वारा सजाए गए कई कार्य हैं और सजावटी के अंदर मल्टीप्रोसेसिंग का सबसे आसान तरीका है। लेकिन दुर्भाग्य से मैं इस समस्या को हल नहीं कर सकता। शायद किसी ने पहले से ही एक ही समस्या हल कर दी है। मैं किसी भी संकेत के लिए आभारी होंगे।

'run_in_parallel' फ़ंक्शन काम करता है जैसे मैं चाहता हूं। दो या दो से अधिक फ़ंक्शंस समानांतर में चलते हैं और पहला फ़ंक्शन पूरा हो जाता है, जो दूसरे फ़ंक्शन को समाप्त करने के लिए मजबूर करता है। जब मैं रैपर (फ़ंक्शन, * तर्क) पर कॉल करता हूं तो फ़ंक्शंस ठीक काम करता है, जब मैं इस तंत्र को सजावटी के अंदर रखता हूं तो मुझे 'पिक फ़ंक्शन नहीं मिल सकता है ... यह' त्रुटि के रूप में नहीं मिला है। विवरण ऊपर

मेरे Traceback पाया जा सकता है:

Traceback (most recent call last): 
    File "C:\Interpreters\Python32\lib\pickle.py", line 679, in save_global 
    klass = getattr(mod, name) 
AttributeError: 'module' object has no attribute 'run_testcase' 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "C:\EskyTests\w_Logger.py", line 19, in <module> 
    logger.run_logger() 
    File "C:\EskyTests\w_Logger.py", line 14, in run_logger 
    self.run_testcase() 
    File "C:\EskyTests\w_Decorators.py", line 14, in wrapper 
    PythonHelper.run_in_parallel([function,args],[recorder.capture]) 
    File "C:\EskyTests\w_PythonHelper.py", line 25, in run_in_parallel 
    process.start() 
    File "C:\Interpreters\Python32\lib\multiprocessing\process.py", line 130, in start 
    self._popen = Popen(self) 
    File "C:\Interpreters\Python32\lib\multiprocessing\forking.py", line 267, in __init__ 
    dump(process_obj, to_child, HIGHEST_PROTOCOL) 
    File "C:\Interpreters\Python32\lib\multiprocessing\forking.py", line 190, in dump 
    ForkingPickler(file, protocol).dump(obj) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 237, in dump 
    self.save(obj) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 344, in save 
    self.save_reduce(obj=obj, *rv) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 432, in save_reduce 
    save(state) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 299, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "C:\Interpreters\Python32\lib\pickle.py", line 623, in save_dict 
    self._batch_setitems(obj.items()) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 656, in _batch_setitems 
    save(v) 
    File "C:\Interpreters\Python32\lib\pickle.py", line 299, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "C:\Interpreters\Python32\lib\pickle.py", line 683, in save_global 
    (obj, module, name)) 
_pickle.PicklingError: Can't pickle <function run_testcase at 0x00000000027725C8>: it's not found as __main__.run_testcase 

उत्तर

1

ट्रिकी, लेकिन मुझे लगता क्या हो रहा है कि check भंडार अनबाउंड विधि के लिए एक संदर्भ जब वर्ग परिभाषित किया गया है है। जब आप run_logger पर कॉल करते हैं तो कार्य उदाहरण बाध्य विधि self.run_testcase के संदर्भ का उपयोग करता है।

मुझे लगता है कि कक्षा की विधि के बजाय run_testcase एक शीर्ष स्तर का फ़ंक्शन बनाने का प्रयास करना सबसे अच्छी बात है।

इसके अलावा, आपके capture फ़ंक्शन शायद आप जो भी उम्मीद करते हैं वह नहीं करेंगे - फ़ंक्शन परिभाषित होने पर वर्तमान समय संग्रहीत किया जाएगा, और प्रत्येक स्क्रीनशॉट पिछले एक से अधिक सहेजा जाएगा। आप शायद फ़ंक्शन के अंदर time.time() पर कॉल करना चाहते हैं।

+0

जब मैं आपके द्वारा वर्णित एक शीर्ष स्तरीय फ़ंक्शन 'run_testcase' बना रहा हूं तो मुझे एक और त्रुटि मिल रही है:' 0x000000000273F9C8 पर फ़ंक्शन run_testcase_proc नहीं उठा सकता है> यह __main __। Run_testcase_proc' जैसा ही ऑब्जेक्ट नहीं है। दुर्भाग्य से यह एक वर्ग का एक तरीका होना चाहिए। मुझे वर्तमान में मौजूदा सजावट को संशोधित करना है, नई कार्यक्षमता को अपनाने के लिए जो 'run_testcase' के साथ समानांतर में किया जाएगा। 'time.time()' फ़ंक्शन एक मामूली समस्या है और केवल कुछ ऑर्डर रखने के लिए उपयोग किया जाता है, यह आसानी से एक संख्या हो सकता है, उदाहरण के लिए 1,2,3 ... मुख्य समस्या सजावट को संशोधित करना था। –

+1

@ falek.marcin: मल्टीप्रोसेसिंग दस्तावेज़ों से: "बाध्य या अनबाउंड विधियों को सीधे विंडोज़ पर लक्षित तर्क के रूप में उपयोग नहीं किया जा सकता है" (http://docs.python.org/dev/library/multiprocessing#windows) –

+0

हो सकता है सजावट को संशोधित करने के लिए एक समाधान या वैकल्पिक समाधान। क्या किसी को यह पता है कि इसे अलग तरीके से कैसे हल किया जाए? –

4

जो फ़ंक्शन आप Process.__init__() पर जा रहे हैं वह विंडोज में पिकलेबल नहीं है। 16.6 multiprocessing - Programming guidelines - Windows पढ़ें।

शीर्ष-स्तरीय फ़ंक्शन के साथ आपकी त्रुटि के संबंध में - मुझे संदेह है कि जिस तरह से आपने इसे परिभाषित किया है, यह हर बार अलग-अलग उत्पन्न होता है और इस प्रकार वास्तव में बच्चे में "एक ही वस्तु नहीं है"। मैं सुझाव देता हूं कि यदि आपको वास्तव में परिष्कार के स्तर की आवश्यकता है तो प्रतिबिंब का उपयोग करके पर कॉल करने के लिए एक सरल शीर्ष-स्तरीय फ़ंक्शन को पारित करने का सुझाव दिया गया है। अद्यतन: इससे सहायता नहीं मिली

अद्यतन:

मैं run_testcase, run_in_parallel और capture undecorating द्वारा यह काम कर दिया।@check डेकोरेटर ही कार्यक्षमता के साथ def wrapper(function,*args) से बदला गया:

import traceback 
def wrapper(function,*args): 
    try: 
     recorder=Recorder() 
     PythonHelper().run_in_parallel([function,args],[recorder.capture]) 
     print("success") 
    except Exception,e: 
     print("failure: "+traceback.format_exc(10)) 

मुख्य:

from w_Decorators import wrapper 

if __name__=="__main__": 
    logger=Logger() 
    wrapper(logger.run_testcase) 

बस के रूप में मैंने सोचा था कि - सजाया वस्तुओं picklable नहीं हैं।

+0

क्या आप दिखा सकते हैं कि आप मेरे उदाहरण के आधार पर ऐसा कैसे करेंगे? –

+0

उपरोक्त मेरे संपादन देखें। वैसे, run_in_parallel() में तर्क गलत हो सकता है। –

+0

_ @ चेक सजावट को समान कार्यक्षमता के साथ डीफ़ रैपर (फ़ंक्शन, * तर्क) के साथ प्रतिस्थापित किया गया था, यह कोई भी कार्यक्षमता नहीं है। ध्यान दें कि मैंने लिखा है कि ** मुझे ** एक सजावटी वाक्यविन्यास का उपयोग करना होगा। मेरे पास अभी बहुत सारी विधियां हैं जो इस तरह से सजाए गए हैं। –

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