मल्टीप्रोसेसिंग के कारण अजगर दुर्घटनाग्रस्त हो जाता है और एक त्रुटि के कारण दूसरे धागे में प्रगति हो सकती है जब कांटा () कहा जाता था


90

मैं पाइथन के लिए अपेक्षाकृत नया हूं और लूप के लिए मल्टीप्रोसेसिंग मॉड्यूल को लागू करने की कोशिश कर रहा हूं।

मेरे पास img_urls में संग्रहीत छवि url की एक सरणी है, जिसे मुझे कुछ Google दृष्टि को डाउनलोड करने और लागू करने की आवश्यकता है।

if __name__ == '__main__':

    img_urls = [ALL_MY_Image_URLS]
    runAll(img_urls)
    print("--- %s seconds ---" % (time.time() - start_time)) 

यह मेरी runAll () विधि है

def runAll(img_urls):
    num_cores = multiprocessing.cpu_count()

    print("Image URLS  {}",len(img_urls))
    if len(img_urls) > 2:
        numberOfImages = 0
    else:
        numberOfImages = 1

    start_timeProcess = time.time()

    pool = multiprocessing.Pool()
    pool.map(annotate,img_urls)
    end_timeProcess = time.time()
    print('\n Time to complete ', end_timeProcess-start_timeProcess)

    print(full_matching_pages)


def annotate(img_path):
    file =  requests.get(img_path).content
    print("file is",file)
    """Returns web annotations given the path to an image."""
    print('Process Working under ',os.getpid())
    image = types.Image(content=file)
    web_detection = vision_client.web_detection(image=image).web_detection
    report(web_detection)

मुझे यह चेतावनी के रूप में मिल रहा है जब मैं इसे चलाता हूं और अजगर दुर्घटनाग्रस्त हो जाता है

objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67567]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67567]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67568]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67568]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67569]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67569]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67571]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67571]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67572]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67572]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

क्या आप OSX पर हैं? तब शायद यह बग रिपोर्ट आपको कुछ संकेत देती है।
IonicSolutions

ओह, मैं OSX पर हूं, मुझे लिंक की ओर इशारा करने के लिए धन्यवाद।
श्रीतेज चिलकमरी

फिर भी किसी भी भाग्य ने OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESजैसा कि उल्लेख करने की कोशिश नहीं की , अभी भी वही त्रुटि मिलती है। @ आईओनिकसोल्यूशन
श्रीतेज चिलकमरी

दुर्भाग्य से, मुझे इस विषय पर कोई विशेष ज्ञान नहीं है। सभी मैं कर सकता हूँ कि संबंधित मुद्दों को खोजने के लिए Google का उपयोग करें, जैसे यह संभव समाधान
IonicSolutions

1
यह उच्च सिएरा के बाद से ऐप्पल के बदलते मैकओएस fork()व्यवहार के कारण है । OBJC_DISABLE_INITIALIZE_FORK_SAFETY=yesतत्काल दुर्घटना व्यवहार बंद चर बदल जाता है कि उनके नए ObjectiveC ढांचे आमतौर पर डिफ़ॉल्ट रूप से अब लागू करता है। यह किसी भी भाषा को प्रभावित कर सकता है जो macOS का उपयोग करके मल्टीथ्रेडिंग / मल्टीप्रोसेसिंग कर fork()रहा है >= 10.13, खासकर जब "मूल एक्सटेंशन" / C कोड एक्सटेंशन का उपयोग किया जाता है।
ट्रिनिट्रॉनएक्स

जवाबों:


219

मैक ओएस हाई सिएरा में मल्टीथ्रेडिंग को प्रतिबंधित करने के लिए अतिरिक्त सुरक्षा के कारण यह त्रुटि होती है। मुझे पता है कि यह उत्तर थोड़ा देर से है, लेकिन मैंने निम्नलिखित विधि का उपयोग करके समस्या को हल किया:

नए मैक ओएस हाई सिएरा सुरक्षा नियमों के तहत मल्टीथ्रेडिंग एप्लिकेशन या स्क्रिप्ट को अनुमति देने के लिए एक पर्यावरण चर .bash_profile सेट करें।

एक टर्मिनल खोलें:

$ nano .bash_profile

फ़ाइल के अंत में निम्न पंक्ति जोड़ें:

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

टर्मिनल से बाहर निकलें, बाहर निकलें, बंद करें और फिर से खोलें। यह देखने के लिए जांचें कि पर्यावरण चर अब सेट है:

$ env

आपको आउटपुट समान दिखाई देगा:

TERM_PROGRAM=Apple_Terminal
SHELL=/bin/bash
TERM=xterm-256color
TMPDIR=/var/folders/pn/vasdlj3ojO#OOas4dasdffJq/T/
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.E7qLFJDSo/Render
TERM_PROGRAM_VERSION=404
TERM_SESSION_ID=NONE
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

अब आपको मल्टीथ्रेडिंग के साथ अपनी अजगर स्क्रिप्ट को चलाने में सक्षम होना चाहिए।


12
यह वास्तव में मेरे लिए इसे हल किया। मैं कई थ्रेड्स में एक बड़े पांडा डेटाफ़्रेम को पुनरावृत्त करना चाहता था, और ऑप द्वारा वर्णित एक ही मुद्दे में भाग गया। इस जवाब ने मेरे लिए समस्या हल कर दी। केवल अंतर यह है कि मैंने जो स्क्रिप्ट चलाई है, उसके साथ मैंने एनवी चर निर्धारित किया है:OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES python my-script.py
रॉडरिगो-सिल्वेरा

3
बहुत बहुत धन्यवाद! रुचि रखने वालों के लिए, इसने मेरे लिए macOS Mojave पर काम किया।
19 को nmetts

इसने मेरी समस्या को हल कर दिया, लेकिन मेरी स्क्रिप्ट बहु-प्रसंस्करण का उपयोग कर रही थी
लॉरसेकेट्स

यह macOS Mojave के साथ मेरी मशीन पर काम करता है, लेकिन तब मेरे pytest परीक्षण समानांतर में नहीं चलते हैं। इससे पहले, यह दुर्घटनाग्रस्त हो गया था, लेकिन कम से कम, यह तेज था ...
एककिलोपरसे

2
इस पर्यावरण चर ने मेरे मैक (
कैटेलिना

0

OBJC_DISABLE_INITIALIZE_FORK_SAFETYवातावरण में बिना झंडे के मेरे लिए जो समाधान काम करता है, उसमें कार्यक्रम शुरू multiprocessing.Poolहोने के तुरंत बाद कक्षा को प्रारंभ करना शामिल है main()

यह संभवत: सबसे तेज़ समाधान संभव नहीं है और मुझे यकीन नहीं है कि यह सभी स्थितियों में काम करता है, हालांकि, मेरे कार्यक्रमों को शुरू करने से पहले कार्यकर्ता जल्दी से पहले गर्म करता है, इससे कोई ... may have been in progress in another thread when fork() was calledत्रुटि नहीं होती है और मुझे इसकी तुलना में एक महत्वपूर्ण प्रदर्शन को बढ़ावा मिलता है मुझे गैर-समानांतर कोड के साथ क्या मिलता है।

मैंने एक सुविधा वर्ग बनाया है Parallelizerजिसे मैं बहुत पहले शुरू कर रहा हूं और फिर अपने कार्यक्रम के पूरे जीवनकाल का उपयोग कर रहा हूं।

# entry point to my program
def main():
    parallelizer = Parallelizer()
    ...

फिर जब भी आप समानांतर करना चाहते हैं:

# this function is parallelized. it is run by each child process.
def processing_function(input):
    ...
    return output

...
inputs = [...]
results = parallelizer.map(
    inputs,
    processing_function
)

और समानांतर श्रेणी:

class Parallelizer:
    def __init__(self):
        self.input_queue = multiprocessing.Queue()
        self.output_queue = multiprocessing.Queue()
        self.pool = multiprocessing.Pool(multiprocessing.cpu_count(),
                                         Parallelizer._run,
                                         (self.input_queue, self.output_queue,))

    def map(self, contents, processing_func):
        size = 0
        for content in contents:
            self.input_queue.put((content, processing_func))
            size += 1
        results = []
        while size > 0:
            result = self.output_queue.get(block=True)
            results.append(result)
            size -= 1
        return results

    @staticmethod
    def _run(input_queue, output_queue):
        while True:
            content, processing_func = input_queue.get(block=True)
            result = processing_func(content)
            output_queue.put(result)

एक चेतावनी: समानांतर कोड को डिबग करना मुश्किल हो सकता है इसलिए मैंने अपनी कक्षा का एक गैर-समानांतर संस्करण भी तैयार किया है जिसे मैं सक्षम करता हूं जब बच्चे की प्रक्रियाओं में कुछ गलत हो जाता है:

class NullParallelizer:
    @staticmethod
    def map(contents, processing_func):
        results = []
        for content in contents:
            results.append(processing_func(content))
        return results
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.