क्या एक पाइथन पूल बनाना संभव नहीं है जो गैर-डिमनिक है? मैं चाहता हूं कि एक पूल एक ऐसे समारोह को कॉल करने में सक्षम हो जिसमें एक और पूल हो। धन्यवाद।पायथन प्रोसेस पूल गैर-डिमनिक?
उत्तर
multiprocessing.pool.Pool
वर्ग, अपने __init__
विधि में कार्यकर्ता प्रक्रियाओं बनाता है उन्हें भूत का बनाता है और उन्हें शुरू होता है, और यह करने के लिए अपने False
daemon
विशेषता फिर से स्थापित करने के लिए संभव नहीं है इससे पहले कि वे शुरू कर रहे हैं (और बाद में इसे अब और अनुमति नहीं है)। लेकिन आप multiprocesing.pool.Pool
(multiprocessing.Pool
केवल एक रैपर फ़ंक्शन है) का अपना उप-वर्ग बना सकते हैं और कार्यकर्ता प्रक्रियाओं के लिए उपयोग किए जाने वाले अपने स्वयं के multiprocessing.Process
उप-वर्ग को प्रतिस्थापित कर सकते हैं, जो हमेशा गैर-डिमनिक होता है।
यहां यह करने का एक पूर्ण उदाहरण है। महत्वपूर्ण भाग शीर्ष पर NoDaemonProcess
और MyPool
दो वर्ग हैं और अंत में MyPool
उदाहरण पर pool.close()
और pool.join()
पर कॉल करने के लिए हैं।
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import multiprocessing
# We must import this explicitly, it is not imported by the top-level
# multiprocessing module.
import multiprocessing.pool
import time
from random import randint
class NoDaemonProcess(multiprocessing.Process):
# make 'daemon' attribute always return False
def _get_daemon(self):
return False
def _set_daemon(self, value):
pass
daemon = property(_get_daemon, _set_daemon)
# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(multiprocessing.pool.Pool):
Process = NoDaemonProcess
def sleepawhile(t):
print("Sleeping %i seconds..." % t)
time.sleep(t)
return t
def work(num_procs):
print("Creating %i (daemon) workers and jobs in child." % num_procs)
pool = multiprocessing.Pool(num_procs)
result = pool.map(sleepawhile,
[randint(1, 5) for x in range(num_procs)])
# The following is not really needed, since the (daemon) workers of the
# child's pool are killed when the child is terminated, but it's good
# practice to cleanup after ourselves anyway.
pool.close()
pool.join()
return result
def test():
print("Creating 5 (non-daemon) workers and jobs in main process.")
pool = MyPool(5)
result = pool.map(work, [randint(1, 5) for x in range(5)])
pool.close()
pool.join()
print(result)
if __name__ == '__main__':
test()
होने के लिए डिमनिक प्रक्रियाओं की अनुमति नहीं है उपरोक्त कोड मेरे लिए लटक रहा है। विशेष रूप से यह पूल (क्लोज़() के अंदर काम() में लटका हुआ प्रतीत होता है। क्या मुझसे कुछ छूट रहा है ? –
मैंने अभी पाइथन 2.7/3.2 ("प्रिंट" लाइनों को ठीक करने के बाद) लिनक्स और पायथन 2.6/2.7/3.2 ओएस एक्स लिनक्स और पायथन 2.7/3.2 पर ओएस एक्स पर ठीक काम किया है लेकिन कोड वास्तव में लटका है ओएस एक्स (शेर) पर पायथन 2.6 के साथ। यह मल्टीप्रोसेसिंग मॉड्यूल में एक बग प्रतीत होता है, जो तय हो गया है, लेकिन मैंने वास्तव में बग ट्रैकर की जांच नहीं की है। –
यह वास्तव में मल्टीप्रोसेसिंग मॉड्यूल में तय किया जाना चाहिए (गैर-डेमोनिक श्रमिकों के लिए एक विकल्प उपलब्ध होना चाहिए)। क्या कोई जानता है कि इसे कौन बनाए रखता है? –
multiprocessing मॉड्यूल प्रक्रियाओं या धागे के साथ पूल उपयोग करने के लिए एक अच्छा इंटरफ़ेस है। आपके वर्तमान उपयोग के मामले के आधार पर, आप अपने बाहरी पूल के लिए multiprocessing.pool.ThreadPool
का उपयोग करने पर विचार कर सकते हैं, जिसके परिणामस्वरूप प्रक्रियाओं के विपरीत (जो भीतर से प्रक्रियाओं को फैलाने की अनुमति देता है)।
यह Gil द्वारा सीमित किया जा सकता है, लेकिन मेरी विशेष मामले में के रूप में बनाया here दूर ThreadPool
साथ समाधान अधिक महत्वपूर्ण बाहरी Pool
से, प्रक्रियाओं के लिए स्टार्टअप समय (मैं दोनों का परीक्षण किया)।
यह वास्तव में Threads
के लिए Processes
स्वैप करने के लिए आसान है। ThreadPool
समाधान here या here का उपयोग कैसे करें के बारे में और पढ़ें।
मुझे जिस मुद्दे का सामना करना पड़ा वह मॉड्यूल के बीच ग्लोबल्स आयात करने की कोशिश में था, जिससे प्रोसेसपूल() लाइन को कई बार मूल्यांकन किया जा सकता था।
globals.py
from processing import Manager, Lock
from pathos.multiprocessing import ProcessPool
from pathos.threading import ThreadPool
class SingletonMeta(type):
def __new__(cls, name, bases, dict):
dict['__deepcopy__'] = dict['__copy__'] = lambda self, *args: self
return super(SingletonMeta, cls).__new__(cls, name, bases, dict)
def __init__(cls, name, bases, dict):
super(SingletonMeta, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance = super(SingletonMeta, cls).__call__(*args, **kw)
return cls.instance
def __deepcopy__(self, item):
return item.__class__.instance
class Globals(object):
__metaclass__ = SingletonMeta
"""
This class is a workaround to the bug: AssertionError: daemonic processes are not allowed to have children
The root cause is that importing this file from different modules causes this file to be reevalutated each time,
thus ProcessPool() gets reexecuted inside that child thread, thus causing the daemonic processes bug
"""
def __init__(self):
print "%s::__init__()" % (self.__class__.__name__)
self.shared_manager = Manager()
self.shared_process_pool = ProcessPool()
self.shared_thread_pool = ThreadPool()
self.shared_lock = Lock() # BUG: Windows: global name 'lock' is not defined | doesn't affect cygwin
फिर सुरक्षित रूप से कहीं और से अपने कोड में आयात
from globals import Globals
Globals().shared_manager
Globals().shared_process_pool
Globals().shared_thread_pool
Globals().shared_lock
AFAIK, कोई यह संभव नहीं है सभी पूल में कार्यकर्ता daemonized रहे हैं और यह __inject संभव नहीं है निर्भरता__, बीटीडब्लू मैं आपके प्रश्न के दूसरे भाग को समझ नहीं पा रहा हूं, 'मैं चाहता हूं कि एक पूल एक ऐसे समारोह को कॉल करने में सक्षम हो जिसमें एक और पूल है' और यह कैसे इस तथ्य में हस्तक्षेप करता है कि मजदूरों को निंदा किया जाता है। – mouad
क्योंकि अगर फ़ंक्शन में एक पूल होता है जो फ़ंक्शन बी चलाता है जिसमें एक पूल होता है जो फ़ंक्शन सी चलाता है, बी में कोई समस्या है कि यह एक डेमॉन प्रक्रिया में चल रहा है, और डेमॉन प्रक्रियाएं प्रक्रियाएं नहीं बना सकती हैं। 'AssertionError: बच्चों को – Max