পাইথনে মাল্টিপ্রসেসিং সারি কীভাবে ব্যবহার করবেন?


94

পাইথনটিতে মাল্টিপ্রসেসিং সারি কীভাবে কাজ করে এবং কীভাবে এটি প্রয়োগ করা যায় তা বোঝার চেষ্টা করতে আমার অনেক সমস্যা হচ্ছে। আসুন বলুন যে আমার কাছে দুটি পাইথন মডিউল রয়েছে যা একটি ভাগ করা ফাইল থেকে ডেটা অ্যাক্সেস করে, আসুন এই দুটি মডিউলকে একজন লেখক এবং পাঠক হিসাবে কল করুন। আমার পরিকল্পনাটি হ'ল পাঠক ও লেখক উভয়ই অনুরোধকে দুটি পৃথক মাল্টিপ্রসেসিং কাতারে রাখবেন এবং তারপরে একটি তৃতীয় প্রক্রিয়া এই অনুরোধগুলিকে একটি লুপে পপ করুন এবং এরূপে কার্যকর করুন।

আমার মূল সমস্যাটি হ'ল আমি বুঝতে পারি না যে মাল্টিপ্রসেসিং.কুই সঠিকভাবে কীভাবে প্রয়োগ করতে হবে, আপনি প্রতিটি প্রক্রিয়াটির জন্য বস্তুটি সত্যই ইনস্ট্যান্ট করতে পারবেন না যেহেতু তারা পৃথক কাতারে থাকবে, আপনি কীভাবে নিশ্চিত হন যে সমস্ত প্রক্রিয়া একটি ভাগ করা কাতারের সাথে সম্পর্কিত (বা এই ক্ষেত্রে, সারি)


4
আপনি যখন প্যারেন্ট প্রসেসে ইনস্ট্যান্ট করবেন তখন প্রতিটি প্রক্রিয়া ক্লাসে প্যারামিটার হিসাবে পাস করুন।
জোয়েল করনেট

উত্তর:


122

আমার মূল সমস্যাটি হ'ল আমি বুঝতে পারি না যে মাল্টিপ্রসেসিং.কুই সঠিকভাবে কীভাবে প্রয়োগ করতে হবে, আপনি প্রতিটি প্রক্রিয়াটির জন্য বস্তুটি সত্যই ইনস্ট্যান্ট করতে পারবেন না যেহেতু তারা পৃথক কাতারে থাকবে, আপনি কীভাবে নিশ্চিত হন যে সমস্ত প্রক্রিয়া একটি ভাগ করা কাতারের সাথে সম্পর্কিত (বা এই ক্ষেত্রে, সারি)

এটি একটি পাঠক এবং লেখকের একক সারিতে ভাগ করার একটি সাধারণ উদাহরণ ... লেখক পাঠকের কাছে একটি সংখ্যক পূর্ণসংখ্যার প্রেরণ করে; লেখক যখন সংখ্যার বাইরে চলে যায়, তখন এটি 'সম্পন্ন' প্রেরণ করে, যা পাঠককে পড়ার লুপ থেকে বেরিয়ে আসতে দেয়।

from multiprocessing import Process, Queue
import time
import sys

def reader_proc(queue):
    ## Read from the queue; this will be spawned as a separate Process
    while True:
        msg = queue.get()         # Read from the queue and do nothing
        if (msg == 'DONE'):
            break

def writer(count, queue):
    ## Write to the queue
    for ii in range(0, count):
        queue.put(ii)             # Write 'count' numbers into the queue
    queue.put('DONE')

if __name__=='__main__':
    pqueue = Queue() # writer() writes to pqueue from _this_ process
    for count in [10**4, 10**5, 10**6]:             
        ### reader_proc() reads from pqueue as a separate process
        reader_p = Process(target=reader_proc, args=((pqueue),))
        reader_p.daemon = True
        reader_p.start()        # Launch reader_proc() as a separate python process

        _start = time.time()
        writer(count, pqueue)    # Send a lot of stuff to reader()
        reader_p.join()         # Wait for the reader to finish
        print("Sending {0} numbers to Queue() took {1} seconds".format(count, 
            (time.time() - _start)))

13
দুর্দান্ত উদাহরণ। ওপি'র বিভ্রান্তি দূর করার জন্য যেমন অতিরিক্ত তথ্য হিসাবে ... এই উদাহরণটি দেখায় যে একটি ভাগ করা সারি মাস্টার প্রক্রিয়া থেকে উদ্ভূত হওয়া দরকার, যা এর পরে তার সমস্ত উপস্থানে চলে যায় is ডেটা ভাগ করে নেওয়ার জন্য দুটি সম্পূর্ণ অপ্রাসঙ্গিক প্রক্রিয়া করার জন্য, তাদের অবশ্যই কিছু কেন্দ্রীয় বা সম্পর্কিত নেটওয়ার্ক ডিভাইস (উদাহরণস্বরূপ সকেট) মাধ্যমে যোগাযোগ করতে হবে। কিছু তথ্য সমন্বয় করতে হবে।
jdi

4
চমৎকার উদাহরণ .. আমি এই বিষয়েও নতুন .. আমার যদি একই লক্ষ্য ফাংশন (বিভিন্ন যুক্তি সহ) চালিত একাধিক প্রক্রিয়া থাকে তবে কীভাবে নিশ্চিত হওয়া যায় যে ডেটা কাতারে রাখার সময় তারা সংঘর্ষে লিপ্ত না হয় .. লক প্রয়োজনীয় ?
WYSIWYG

@ ভারত_আইএনগার মাল্টিপ্রসেসিং মডিউল ডকুমেন্টেশন থেকে, এটিতে বলা হয়েছে যে কয়েকটি লক / সেমোফোর ব্যবহার করে ক্যু প্রয়োগ করা হয়েছে। সুতরাং যখন আপনি get () এবং (অবজেক্ট) সারি পদ্ধতি ব্যবহার করেন, তখন অন্য কোনও প্রক্রিয়া / থ্রেড কিছু পাওয়ার জন্য বা কাতারে রাখার চেষ্টা করা থাকলে কাতারটি ব্লক হয়ে যাবে। সুতরাং আপনাকে এটি ম্যানুয়ালি লক করার বিষয়ে চিন্তা করার দরকার নেই।
এলমেলে

4
সুস্পষ্ট স্টপ শর্তগুলি অন্তর্নিহিত স্টপ অবস্থার চেয়ে ভাল
মাইক পেনিংটন

4
কিউসাইজ শূন্যে যেতে পারে যদি কিউ পাঠকরা কিউ লেখকের হারকে ছাড়িয়ে যান
মাইক পেনিংটন

8

" from queue import Queue" তে কোনও মডিউল বলা হয় না queue, পরিবর্তে multiprocessingএটি ব্যবহার করা উচিত। সুতরাং, এটি " from multiprocessing import Queue" এর মতো দেখতে হবে


11
কয়েক বছর দেরিতে, ব্যবহার multiprocessing.Queueকরা সঠিক। সাধারণ Queue.Queueপাইথন থ্রেডের জন্য ব্যবহৃত হয় । আপনি যখন Queue.Queueমাল্টিপ্রসেসিং দিয়ে ব্যবহার করার চেষ্টা করবেন , প্রতিটি শিশু প্রক্রিয়াতে কাতারে অবজেক্টের অনুলিপি তৈরি হবে এবং শিশু প্রক্রিয়াগুলি কখনই আপডেট হবে না। মূলত, Queue.Queueএকটি গ্লোবাল শেয়ার্ড অবজেক্ট multiprocessing.Queueব্যবহার করে কাজ করে এবং আইপিসি ব্যবহার করে কাজ করে। দেখুন: stackoverflow.com/questions/925100/...
মাইকেল Guffre

5

এখানে একটি মৃত সহজ ব্যবহার রয়েছে multiprocessing.Queueএবং multiprocessing.Processএটি কলকারীদের একটি পৃথক প্রক্রিয়াতে "ইভেন্ট" প্লাস যুক্তিগুলি প্রেরণের অনুমতি দেয় যা প্রক্রিয়াটির "do_" পদ্ধতিতে ইভেন্টটি প্রেরণ করে। (পাইথন ৩.৪++)

import multiprocessing as mp
import collections

Msg = collections.namedtuple('Msg', ['event', 'args'])

class BaseProcess(mp.Process):
    """A process backed by an internal queue for simple one-way message passing.
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.queue = mp.Queue()

    def send(self, event, *args):
        """Puts the event and args as a `Msg` on the queue
        """
       msg = Msg(event, args)
       self.queue.put(msg)

    def dispatch(self, msg):
        event, args = msg

        handler = getattr(self, "do_%s" % event, None)
        if not handler:
            raise NotImplementedError("Process has no handler for [%s]" % event)

        handler(*args)

    def run(self):
        while True:
            msg = self.queue.get()
            self.dispatch(msg)

ব্যবহার:

class MyProcess(BaseProcess):
    def do_helloworld(self, arg1, arg2):
        print(arg1, arg2)

if __name__ == "__main__":
    process = MyProcess()
    process.start()
    process.send('helloworld', 'hello', 'world')

sendপিতা বা মাতা প্রক্রিয়ায় ঘটে, do_*শিশু প্রক্রিয়ায় ঘটে।

আমি কোনও ব্যতিক্রম হ্যান্ডলিং বাদ দিয়েছি যা স্পষ্টতই রান লুপটিকে বাধাগ্রস্থ করবে এবং শিশু প্রক্রিয়াটি প্রস্থান করবে। আপনি runব্লকিং বা অন্য যে কোনও কিছু নিয়ন্ত্রণ করতে ওভাররাইড করে এটিকে কাস্টমাইজ করতে পারেন ।

এটি কেবলমাত্র আপনার পরিস্থিতিতে একক কর্মী প্রক্রিয়াধীন পরিস্থিতিতে কার্যকর তবে আমি মনে করি এটি আরও কিছুটা অবজেক্ট-অভিমুখীকরণের সাথে একটি সাধারণ দৃশ্যে প্রদর্শিত এই প্রশ্নের একটি প্রাসঙ্গিক উত্তর।


4
অসামান্য উত্তর! ধন্যবাদ. +50 :)
কিমিক্লাস

3

বৃহত্তর পান্ডাস ডাটাফ্রেমগুলি অতিক্রম করার জন্য সারি ব্যবহার করে মাল্টিপ্রসেসিংয়ের একটি উপায় সেট আপ করার চেষ্টা করার সময় আমার স্ট্যাক ওভারফ্লো এবং ওয়েব জুড়ে একাধিক উত্তর ছিল। আমার কাছে মনে হয়েছিল যে প্রতিটি উত্তর একই ধরণের সমাধানগুলিকে পুনরায় পুনরায় পুনরায় পুনরায় পুনরায় পুনরায় পুনরায় পুনরায় পুনরুক্ত করে চলেছে এবং এ জাতীয় গণনা স্থাপনের সময় অবশ্যই কোনও সমস্যা অবশ্যই আসবে। সমস্যাটি হ'ল একই সময়ে খেলতে প্রচুর জিনিস রয়েছে। কার্য সংখ্যা, কর্মীর সংখ্যা, প্রতিটি কার্যের সময়কাল এবং কার্য সম্পাদনের সময় সম্ভাব্য ব্যতিক্রম। এগুলি সমস্তই সিঙ্ক্রোনাইজেশনকে জটিল করে তোলে এবং বেশিরভাগ উত্তরগুলি কীভাবে আপনি এটি সম্পর্কে যেতে পারেন তা সম্বোধন করে না। তাই কয়েক ঘন্টার জন্য ঘোরাফেরা করার পরে এটি আমার গ্রহণ, আশা করি বেশিরভাগ লোকেরা এটির দরকারী হিসাবে খুঁজে পেতে পারে gener

কোনও কোডিং উদাহরণের আগে কিছু চিন্তা। যেহেতু queue.Emptyবা queue.qsize()বা অন্য কোনও অনুরূপ পদ্ধতি প্রবাহ নিয়ন্ত্রণের জন্য অবিশ্বাস্য, এর মতো যে কোনও কোড

while True:
    try:
        task = pending_queue.get_nowait()
    except queue.Empty:
        break

বোগাস এটি মিলিসেকেন্ড পরে অন্য কোনও কাজ সারিতে সরে গেলেও শ্রমিককে হত্যা করবে। শ্রমিকটি পুনরুদ্ধার করতে পারবেন না এবং কিছুক্ষণ পরে সমস্ত শ্রমিক অদৃশ্য হয়ে যাবে কারণ তারা এলোমেলোভাবে ক্রমটি মুহূর্তের জন্য খালি পেয়েছে। শেষ ফলাফলটি হ'ল মূল মাল্টিপ্রসেসিং ফাংশন (প্রসেসগুলিতে জয়েন () সহ একটি) সমস্ত কাজ সমাপ্ত না করে ফিরে আসবে। ভাল লাগল সৌভাগ্যক্রমে ডিবাগিং এর মাধ্যমে যদি আপনার কয়েক হাজার কাজ থাকে এবং কয়েকটি অনুপস্থিত থাকে।

অন্য সমস্যাটি হ'ল সেন্ডিনেল মান ব্যবহার। অনেক লোক কাতারটির শেষে পতাকাটি প্রেরণ করতে কাতারে একটি সেন্ডিনেল মান যুক্ত করার পরামর্শ দিয়েছে। তবে একে ঠিক পতাকা কার কাছে? যদি সেখানে এন কর্মী থাকে, ধরে নেওয়া হয় যে এন উপলব্ধ এবং নেওয়া উপলব্ধ কোরগুলির সংখ্যা, তবে একটি একক সেন্ডিনেল মান কেবলমাত্র এক শ্রমিকের সারিটির সমাপ্তি পতাকাঙ্কিত করবে। বাকী সমস্ত কর্মী যখন আরও কিছু না রাখেন তখন আরও কাজের জন্য অপেক্ষা করতে বসবেন। সাধারণ উদাহরণগুলি আমি দেখেছি

while True:
    task = pending_queue.get()
    if task == SOME_SENTINEL_VALUE:
        break

একজন কর্মী সেন্ডিনেল মান পাবেন এবং বাকিরা অনির্দিষ্টকালের জন্য অপেক্ষা করবেন। আমি যে পোস্টটি দেখতে পাইনি তা উল্লেখ করেই বলেছি যে আপনার যত শ্রমিক রয়েছে তার চেয়ে কম সময়ে যতবার কাতারে সেন্ডিনেল মান জমা করতে হবে যাতে সেগুলির সমস্ত এটি পায়।

অন্য সমস্যাটি হ'ল কার্য সম্পাদনের সময় ব্যতিক্রমগুলি পরিচালনা করা। আবার এগুলি ধরা এবং পরিচালনা করা উচিত। তদুপরি, আপনার যদি একটি completed_tasksসারি থাকে তবে কাজটি সম্পন্ন করার সিদ্ধান্ত নেওয়ার আগে আপনার স্বাধীনভাবে একটি নির্বিচার পদ্ধতিতে গণনা করা উচিত যে কয়টি আইটেম সারিতে রয়েছে। আবার সারি আকারের উপর নির্ভর করা ব্যর্থ হতে বাধ্য এবং অপ্রত্যাশিত ফলাফলগুলি ফেরত দেয়।

নীচের উদাহরণে, par_proc()ফাংশনটি কোনও কার্যকরী তালিকাভুক্ত করবে যা কার্যবিধির সাথে কোনও নামযুক্ত যুক্তি এবং মানগুলির পাশাপাশি এই কার্যগুলি সম্পাদন করা উচিত।

import multiprocessing as mp
import dill as pickle
import queue
import time
import psutil

SENTINEL = None


def do_work(tasks_pending, tasks_completed):
    # Get the current worker's name
    worker_name = mp.current_process().name

    while True:
        try:
            task = tasks_pending.get_nowait()
        except queue.Empty:
            print(worker_name + ' found an empty queue. Sleeping for a while before checking again...')
            time.sleep(0.01)
        else:
            try:
                if task == SENTINEL:
                    print(worker_name + ' no more work left to be done. Exiting...')
                    break

                print(worker_name + ' received some work... ')
                time_start = time.perf_counter()
                work_func = pickle.loads(task['func'])
                result = work_func(**task['task'])
                tasks_completed.put({work_func.__name__: result})
                time_end = time.perf_counter() - time_start
                print(worker_name + ' done in {} seconds'.format(round(time_end, 5)))
            except Exception as e:
                print(worker_name + ' task failed. ' + str(e))
                tasks_completed.put({work_func.__name__: None})


def par_proc(job_list, num_cpus=None):

    # Get the number of cores
    if not num_cpus:
        num_cpus = psutil.cpu_count(logical=False)

    print('* Parallel processing')
    print('* Running on {} cores'.format(num_cpus))

    # Set-up the queues for sending and receiving data to/from the workers
    tasks_pending = mp.Queue()
    tasks_completed = mp.Queue()

    # Gather processes and results here
    processes = []
    results = []

    # Count tasks
    num_tasks = 0

    # Add the tasks to the queue
    for job in job_list:
        for task in job['tasks']:
            expanded_job = {}
            num_tasks = num_tasks + 1
            expanded_job.update({'func': pickle.dumps(job['func'])})
            expanded_job.update({'task': task})
            tasks_pending.put(expanded_job)

    # Use as many workers as there are cores (usually chokes the system so better use less)
    num_workers = num_cpus

    # We need as many sentinels as there are worker processes so that ALL processes exit when there is no more
    # work left to be done.
    for c in range(num_workers):
        tasks_pending.put(SENTINEL)

    print('* Number of tasks: {}'.format(num_tasks))

    # Set-up and start the workers
    for c in range(num_workers):
        p = mp.Process(target=do_work, args=(tasks_pending, tasks_completed))
        p.name = 'worker' + str(c)
        processes.append(p)
        p.start()

    # Gather the results
    completed_tasks_counter = 0
    while completed_tasks_counter < num_tasks:
        results.append(tasks_completed.get())
        completed_tasks_counter = completed_tasks_counter + 1

    for p in processes:
        p.join()

    return results

এবং এখানে উপরের কোডটির বিরুদ্ধে চালানোর জন্য একটি পরীক্ষা দেওয়া হচ্ছে

def test_parallel_processing():
    def heavy_duty1(arg1, arg2, arg3):
        return arg1 + arg2 + arg3

    def heavy_duty2(arg1, arg2, arg3):
        return arg1 * arg2 * arg3

    task_list = [
        {'func': heavy_duty1, 'tasks': [{'arg1': 1, 'arg2': 2, 'arg3': 3}, {'arg1': 1, 'arg2': 3, 'arg3': 5}]},
        {'func': heavy_duty2, 'tasks': [{'arg1': 1, 'arg2': 2, 'arg3': 3}, {'arg1': 1, 'arg2': 3, 'arg3': 5}]},
    ]

    results = par_proc(task_list)

    job1 = sum([y for x in results if 'heavy_duty1' in x.keys() for y in list(x.values())])
    job2 = sum([y for x in results if 'heavy_duty2' in x.keys() for y in list(x.values())])

    assert job1 == 15
    assert job2 == 21

কিছু ব্যতিক্রম সহ আরও একটি one

def test_parallel_processing_exceptions():
    def heavy_duty1_raises(arg1, arg2, arg3):
        raise ValueError('Exception raised')
        return arg1 + arg2 + arg3

    def heavy_duty2(arg1, arg2, arg3):
        return arg1 * arg2 * arg3

    task_list = [
        {'func': heavy_duty1_raises, 'tasks': [{'arg1': 1, 'arg2': 2, 'arg3': 3}, {'arg1': 1, 'arg2': 3, 'arg3': 5}]},
        {'func': heavy_duty2, 'tasks': [{'arg1': 1, 'arg2': 2, 'arg3': 3}, {'arg1': 1, 'arg2': 3, 'arg3': 5}]},
    ]

    results = par_proc(task_list)

    job1 = sum([y for x in results if 'heavy_duty1' in x.keys() for y in list(x.values())])
    job2 = sum([y for x in results if 'heavy_duty2' in x.keys() for y in list(x.values())])

    assert not job1
    assert job2 == 21

আশা করি এটি সহায়ক।


2

আমরা এর দুটি সংস্করণ বাস্তবায়িত করেছি, একটি সাধারণ মাল্টি থ্রেড পুল যা আমাদের জীবনকে অনেক সহজ করে তোলে এবং দ্বিতীয় সংস্করণে প্রসেস ব্যবহার করা হয় , যা কলযোগ্যতার ক্ষেত্রে কম নমনীয় এবং ডিলের জন্য অতিরিক্ত কল।

হিমায়িত_পুলকে সত্যে সেট করা যতক্ষণ না উভয় শ্রেণিতেই ফিনিশ_পুল_ক্যু না বলা হয় ততক্ষণ কার্যকর করা স্থির হয়ে যায়।

থ্রেড সংস্করণ:

'''
Created on Nov 4, 2019

@author: Kevin
'''
from threading import Lock, Thread
from Queue import Queue
import traceback
from helium.loaders.loader_retailers import print_info
from time import sleep
import signal
import os

class ThreadPool(object):
    def __init__(self, queue_threads, *args, **kwargs):
        self.frozen_pool = kwargs.get('frozen_pool', False)
        self.print_queue = kwargs.get('print_queue', True)
        self.pool_results = []
        self.lock = Lock()
        self.queue_threads = queue_threads
        self.queue = Queue()
        self.threads = []

        for i in range(self.queue_threads):
            t = Thread(target=self.make_pool_call)
            t.daemon = True
            t.start()
            self.threads.append(t)

    def make_pool_call(self):
        while True:
            if self.frozen_pool:
                #print '--> Queue is frozen'
                sleep(1)
                continue

            item = self.queue.get()
            if item is None:
                break

            call = item.get('call', None)
            args = item.get('args', [])
            kwargs = item.get('kwargs', {})
            keep_results = item.get('keep_results', False)

            try:
                result = call(*args, **kwargs)

                if keep_results:
                    self.lock.acquire()
                    self.pool_results.append((item, result))
                    self.lock.release()

            except Exception as e:
                self.lock.acquire()
                print e
                traceback.print_exc()
                self.lock.release()
                os.kill(os.getpid(), signal.SIGUSR1)

            self.queue.task_done()

    def finish_pool_queue(self):
        self.frozen_pool = False

        while self.queue.unfinished_tasks > 0:
            if self.print_queue:
                print_info('--> Thread pool... %s' % self.queue.unfinished_tasks)
            sleep(5)

        self.queue.join()

        for i in range(self.queue_threads):
            self.queue.put(None)

        for t in self.threads:
            t.join()

        del self.threads[:]

    def get_pool_results(self):
        return self.pool_results

    def clear_pool_results(self):
        del self.pool_results[:]

প্রক্রিয়া সংস্করণ:

  '''
Created on Nov 4, 2019

@author: Kevin
'''
import traceback
from helium.loaders.loader_retailers import print_info
from time import sleep
import signal
import os
from multiprocessing import Queue, Process, Value, Array, JoinableQueue, Lock,\
    RawArray, Manager
from dill import dill
import ctypes
from helium.misc.utils import ignore_exception
from mem_top import mem_top
import gc

class ProcessPool(object):
    def __init__(self, queue_processes, *args, **kwargs):
        self.frozen_pool = Value(ctypes.c_bool, kwargs.get('frozen_pool', False))
        self.print_queue = kwargs.get('print_queue', True)
        self.manager = Manager()
        self.pool_results = self.manager.list()
        self.queue_processes = queue_processes
        self.queue = JoinableQueue()
        self.processes = []

        for i in range(self.queue_processes):
            p = Process(target=self.make_pool_call)
            p.start()
            self.processes.append(p)

        print 'Processes', self.queue_processes

    def make_pool_call(self):
        while True:
            if self.frozen_pool.value:
                sleep(1)
                continue

            item_pickled = self.queue.get()

            if item_pickled is None:
                #print '--> Ending'
                self.queue.task_done()
                break

            item = dill.loads(item_pickled)

            call = item.get('call', None)
            args = item.get('args', [])
            kwargs = item.get('kwargs', {})
            keep_results = item.get('keep_results', False)

            try:
                result = call(*args, **kwargs)

                if keep_results:
                    self.pool_results.append(dill.dumps((item, result)))
                else:
                    del call, args, kwargs, keep_results, item, result

            except Exception as e:
                print e
                traceback.print_exc()
                os.kill(os.getpid(), signal.SIGUSR1)

            self.queue.task_done()

    def finish_pool_queue(self, callable=None):
        self.frozen_pool.value = False

        while self.queue._unfinished_tasks.get_value() > 0:
            if self.print_queue:
                print_info('--> Process pool... %s' % (self.queue._unfinished_tasks.get_value()))

            if callable:
                callable()

            sleep(5)

        for i in range(self.queue_processes):
            self.queue.put(None)

        self.queue.join()
        self.queue.close()

        for p in self.processes:
            with ignore_exception: p.join(10)
            with ignore_exception: p.terminate()

        with ignore_exception: del self.processes[:]

    def get_pool_results(self):
        return self.pool_results

    def clear_pool_results(self):
        del self.pool_results[:]
def test(eg):
        print 'EG', eg

হয় সাথে কল:

tp = ThreadPool(queue_threads=2)
tp.queue.put({'call': test, 'args': [random.randint(0, 100)]})
tp.finish_pool_queue()

বা

pp = ProcessPool(queue_processes=2)
pp.queue.put(dill.dumps({'call': test, 'args': [random.randint(0, 100)]}))
pp.queue.put(dill.dumps({'call': test, 'args': [random.randint(0, 100)]}))
pp.finish_pool_queue()

0

2 টি স্ট্যান্ডএলোন প্রোগ্রামের মধ্যে একটি সারিতে কোনও বার্তা প্রেরণ প্রদর্শনের জন্য কেবল একটি সাধারণ এবং সাধারণ উদাহরণ তৈরি করেছেন। এটি সরাসরি ওপি-র প্রশ্নের উত্তর দেয় না তবে ধারণাটি নির্দেশ করার ক্ষেত্রে এটি পরিষ্কার হওয়া উচিত।

সার্ভার:

multiprocessing-queue-manager-server.py

import asyncio
import concurrent.futures
import multiprocessing
import multiprocessing.managers
import queue
import sys
import threading
from typing import Any, AnyStr, Dict, Union


class QueueManager(multiprocessing.managers.BaseManager):

    def get_queue(self, ident: Union[AnyStr, int, type(None)] = None) -> multiprocessing.Queue:
        pass


def get_queue(ident: Union[AnyStr, int, type(None)] = None) -> multiprocessing.Queue:
    global q

    if not ident in q:
        q[ident] = multiprocessing.Queue()

    return q[ident]


q: Dict[Union[AnyStr, int, type(None)], multiprocessing.Queue] = dict()
delattr(QueueManager, 'get_queue')


def init_queue_manager_server():
    if not hasattr(QueueManager, 'get_queue'):
        QueueManager.register('get_queue', get_queue)


def serve(no: int, term_ev: threading.Event):
    manager: QueueManager
    with QueueManager(authkey=QueueManager.__name__.encode()) as manager:
        print(f"Server address {no}: {manager.address}")

        while not term_ev.is_set():
            try:
                item: Any = manager.get_queue().get(timeout=0.1)
                print(f"Client {no}: {item} from {manager.address}")
            except queue.Empty:
                continue


async def main(n: int):
    init_queue_manager_server()
    term_ev: threading.Event = threading.Event()
    executor: concurrent.futures.ThreadPoolExecutor = concurrent.futures.ThreadPoolExecutor()

    i: int
    for i in range(n):
        asyncio.ensure_future(asyncio.get_running_loop().run_in_executor(executor, serve, i, term_ev))

    # Gracefully shut down
    try:
        await asyncio.get_running_loop().create_future()
    except asyncio.CancelledError:
        term_ev.set()
        executor.shutdown()
        raise


if __name__ == '__main__':
    asyncio.run(main(int(sys.argv[1])))

ক্লায়েন্ট:

multiprocessing-queue-manager-client.py

import multiprocessing
import multiprocessing.managers
import os
import sys
from typing import AnyStr, Union


class QueueManager(multiprocessing.managers.BaseManager):

    def get_queue(self, ident: Union[AnyStr, int, type(None)] = None) -> multiprocessing.Queue:
        pass


delattr(QueueManager, 'get_queue')


def init_queue_manager_client():
    if not hasattr(QueueManager, 'get_queue'):
        QueueManager.register('get_queue')


def main():
    init_queue_manager_client()

    manager: QueueManager = QueueManager(sys.argv[1], authkey=QueueManager.__name__.encode())
    manager.connect()

    message = f"A message from {os.getpid()}"
    print(f"Message to send: {message}")
    manager.get_queue().put(message)


if __name__ == '__main__':
    main()

ব্যবহার

সার্ভার:

$ python3 multiprocessing-queue-manager-server.py N

Nএকটি পূর্ণসংখ্যা যা কতগুলি সার্ভার তৈরি করা উচিত তা নির্দেশ করে। <server-address-N>সার্ভার দ্বারা আউটপুটগুলির একটি অনুলিপি করুন এবং এটিকে প্রতিটিের প্রথম যুক্তি তৈরি করুন multiprocessing-queue-manager-client.py

ক্লায়েন্ট:

python3 multiprocessing-queue-manager-client.py <server-address-1>

ফলাফল

সার্ভার:

Client 1: <item> from <server-address-1>

সংক্ষেপ: https://gist.github.com/89062d639e40110c61c2f88018a8b0e5


ইউপিডি : এখানে একটি প্যাকেজ তৈরি করা হয়েছে

সার্ভার:

import ipcq


with ipcq.QueueManagerServer(address=ipcq.Address.DEFAULT, authkey=ipcq.AuthKey.DEFAULT) as server:
    server.get_queue().get()

ক্লায়েন্ট:

import ipcq


client = ipcq.QueueManagerClient(address=ipcq.Address.DEFAULT, authkey=ipcq.AuthKey.DEFAULT)
client.get_queue().put('a message')

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.