মাল্টিপ্রসেসিং.প্রসেসকে পাস করা কোনও ফাংশনের রিটার্নের মান আমি কীভাবে পুনরুদ্ধার করতে পারি?


190

নীচের উদাহরণ কোডে, আমি ফাংশনের রিটার্ন মানটি পুনরুদ্ধার করতে চাই worker। আমি কীভাবে এটি করতে পারি? কোথায় এই মান সঞ্চিত?

উদাহরণ কোড:

import multiprocessing

def worker(procnum):
    '''worker function'''
    print str(procnum) + ' represent!'
    return procnum


if __name__ == '__main__':
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        jobs.append(p)
        p.start()

    for proc in jobs:
        proc.join()
    print jobs

আউটপুট:

0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>]

আমি সঞ্চিত বস্তুগুলিতে প্রাসঙ্গিক বৈশিষ্ট্যটি খুঁজে পেতে পারি না jobs

উত্তর:


188

যোগাযোগের জন্য ভাগ করা ভেরিয়েবল ব্যবহার করুন । উদাহরণস্বরূপ:

import multiprocessing

def worker(procnum, return_dict):
    '''worker function'''
    print str(procnum) + ' represent!'
    return_dict[procnum] = procnum


if __name__ == '__main__':
    manager = multiprocessing.Manager()
    return_dict = manager.dict()
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,return_dict))
        jobs.append(p)
        p.start()

    for proc in jobs:
        proc.join()
    print return_dict.values()

46
আমি এখানে ব্যবহার multiprocessing.Queueনা করে একটি ব্যবহার করার পরামর্শ দেব Manager। একটি ব্যবহারের Managerজন্য সম্পূর্ণ নতুন প্রক্রিয়া তৈরি হওয়া দরকার, যা যখন করা হয় তখন ওভারকিল হয় Queue
ড্যানো

1
@दानো: আমি অবাক হয়েছি, আমরা যদি কুই () অবজেক্টটি ব্যবহার করি, আমরা প্রতিটি প্রক্রিয়াটির মান ফেরত দেওয়ার সময় নিশ্চিত হতে পারি না। আমি বোঝাতে চাইছি যদি ফলাফলটি অর্ডের প্রয়োজন হয় তবে পরবর্তী কাজটি করার জন্য। কোন প্রক্রিয়া থেকে ঠিক কোন আউটপুট হয় তা আমরা কীভাবে নিশ্চিত করতে পারি
Catbuilts

4
@ গুগলবিল্টস আপনি প্রতিটি প্রক্রিয়া থেকে একটি দ্বিগুণ ফিরিয়ে দিতে পারেন, যেখানে একটি মান হ'ল আপনার যত্ন নেওয়া প্রকৃত প্রত্যাবর্তন মূল্য এবং অন্যটি প্রক্রিয়াটির একটি অনন্য পরিচয়কারী। তবে আমি আরও আশ্চর্য হয়েছি যে কেন আপনাকে জানতে হবে যে কোন প্রক্রিয়া কোন মানটি ফিরিয়ে দিচ্ছে। যদি সেই প্রক্রিয়াটি সম্পর্কে আপনার আসলে যা জানা দরকার, বা আপনার ইনপুটগুলির তালিকা এবং আউটপুটগুলির তালিকার মধ্যে পারস্পরিক সম্পর্ক প্রয়োজন? সেক্ষেত্রে আমি multiprocessing.Pool.mapআপনার কাজের আইটেমগুলির তালিকা প্রক্রিয়া করার জন্য ব্যবহার করার পরামর্শ দেব ।
ড্যানো

4
শুধুমাত্র একটি যুক্তিযুক্ত ফাংশনগুলির জন্য সতর্কতা : ব্যবহার করা উচিত args=(my_function_argument, ),কমা এখানে নোট করুন! অন্যথায় পাইথন অভিযোগ করবে "অবস্থানগত আর্গুমেন্টগুলি অনুপস্থিত"। আমাকে বের করার জন্য 10 মিনিট সময় নিয়েছে। ম্যানুয়াল ব্যবহার পরীক্ষা করুন ("প্রক্রিয়া শ্রেণীর" বিভাগের অধীনে)।
ইউক্লি

2
মাল্টিপ্রিওসেসিং ব্যবহারের বারবারটি ভার্টিকের এক.প্রশাসন (ম্যানেজার) অভিধানটি হ'ল আচারটি (সিরিয়ালাইজ করে) এটি প্রত্যাবর্তিত বস্তু হয়, সুতরাং এটিতে ফিরে আসার জন্য সর্বোচ্চ 2GiB আকারের আচার লাইব্রেরি দ্বারা প্রদত্ত একটি বাধা রয়েছে। প্রত্যাবর্তনকারী অবজেক্টের সিরিয়ালাইজেশন এড়িয়ে যাওয়ার এটির উপায় আছে কি?
হিরশ্মে

67

আমি মনে করি @ সেগা_সাই দ্বারা প্রস্তাবিত পদ্ধতিটি আরও ভাল। তবে এটির সত্যই একটি কোড উদাহরণ প্রয়োজন, সুতরাং এখানে যায়:

import multiprocessing
from os import getpid

def worker(procnum):
    print('I am number %d in process %d' % (procnum, getpid()))
    return getpid()

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes = 3)
    print(pool.map(worker, range(5)))

যা ফেরতের মানগুলি মুদ্রণ করবে:

I am number 0 in process 19139
I am number 1 in process 19138
I am number 2 in process 19140
I am number 3 in process 19139
I am number 4 in process 19140
[19139, 19138, 19140, 19139, 19140]

যদি আপনি map(পাইথন 2 বিল্ট-ইন) এর সাথে পরিচিত হন তবে এটি খুব চ্যালেঞ্জিং হওয়া উচিত নয়। অন্যথায় সেগা_সাই এর লিঙ্কটি একবার দেখুন

কিভাবে ছোট কোড প্রয়োজন তা নোট করুন। (এছাড়াও প্রক্রিয়াগুলি কীভাবে পুনরায় ব্যবহৃত হয় তা লক্ষ করুন)।


1
কোন ধারণা কেন আমার getpid()একই মূল্য একই? আমি পাইথন 3 চালাচ্ছি
zelusp

আমি নিশ্চিত না যে পুল কীভাবে কর্মীদের উপর কার্য বিতরণ করে। যদি তারা সত্যিই দ্রুত হয় তবে তারা সবাই একই কর্মীর কাছে যেতে পারে? এটি কি ধারাবাহিকভাবে ঘটে? এছাড়াও যদি আপনি একটি বিলম্ব যোগ করেন?
চিহ্নিত করুন

আমি এটিও একটি গতি সম্পর্কিত জিনিস বলে ভেবেছিলাম কিন্তু যখন আমি pool.map10 টিরও বেশি প্রসেস ব্যবহার করে 1,000,000 এর পরিসর খাওয়াই তখন আমি প্রায় দুটি পৃথক পিড দেখতে পাই।
zelusp

1
তাহলে আমি নিশ্চিত নই। আমি মনে করি এটির জন্য আলাদা প্রশ্ন খুলতে আগ্রহী হবে।
চিহ্নিত করুন

আপনি যদি প্রতিটি প্রক্রিয়াটিতে আলাদা আলাদা ফাংশন প্রেরণ করতে চান তবে ব্যবহার করুন pool.apply_async: ডকস.পিথন.আর
কাইল

24

এই উদাহরণটি দেখায় যে মাল্টিপ্রসেসিংয়ের একটি তালিকা কীভাবে ব্যবহার করতে হয় an পাইপ উদাহরণগুলি স্বেচ্ছাসেবী সংখ্যক প্রক্রিয়া থেকে স্ট্রিংগুলি ফেরত দিতে:

import multiprocessing

def worker(procnum, send_end):
    '''worker function'''
    result = str(procnum) + ' represent!'
    print result
    send_end.send(result)

def main():
    jobs = []
    pipe_list = []
    for i in range(5):
        recv_end, send_end = multiprocessing.Pipe(False)
        p = multiprocessing.Process(target=worker, args=(i, send_end))
        jobs.append(p)
        pipe_list.append(recv_end)
        p.start()

    for proc in jobs:
        proc.join()
    result_list = [x.recv() for x in pipe_list]
    print result_list

if __name__ == '__main__':
    main()

আউটপুট:

0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
['0 represent!', '1 represent!', '2 represent!', '3 represent!', '4 represent!']

এই সমাধানটি মাল্টিপ্রসেসিংয়ের চেয়ে কম সংস্থান ব্যবহার করে Q কিউ যা ব্যবহার করে

  • একটি নল
  • কমপক্ষে একটি লক
  • একটি বাফার
  • একটি থ্রেড

বা একটি মাল্টিপ্রসেসিং.সম্পূর্ণ কিউ যা ব্যবহার করে

  • একটি নল
  • কমপক্ষে একটি লক

এটি প্রতিটি ধরণের জন্য উত্স তাকান খুব শিক্ষামূলক।


পাইপগুলিকে বৈশ্বিক পরিবর্তনশীল না করে কী করার সর্বোত্তম উপায় হতে পারে?
নিকপিক

আমি সমস্ত গ্লোবাল ডেটা এবং কোড একটি প্রধান ফাংশনে রেখেছি এবং এটি একই কাজ করে। এতে আপনার প্রশ্নের উত্তর হলো কি?
ডেভিড কুলেন

এতে কোনও নতুন মান যুক্ত (প্রেরণ) যুক্ত হওয়ার আগে পাইপটি কি সর্বদা পড়তে হবে?
নিকপিক

+1, ভাল উত্তর। তবে সমাধানটি আরও কার্যকর হওয়ার বিষয়ে, ট্রেডঅফ হ'ল আপনি সমস্ত প্রক্রিয়াটির জন্য Pipeএকটি প্রক্রিয়া বনাম Queueতৈরি করছেন। আমি জানি না যে এটি সব ক্ষেত্রেই আরও দক্ষ হয়ে ওঠে।
sudo

2
যদি রিটার্নিং অবজেক্টটি বড় হয় তবে এই উত্তরটি অচলাবস্থার সৃষ্টি করে। প্রথমে proc.join () না করে প্রথমে আমি রিটার্ন মানটি পুনরুদ্ধার করার চেষ্টা করব এবং তারপরে যোগ দিন do
এল পেস

21

কোনও কারণে, আমি Queueকোথাও কীভাবে এটি করব তার একটি সাধারণ উদাহরণ আমি খুঁজে পাইনি (পাইথনের ডকের উদাহরণগুলিও একাধিক প্রক্রিয়া উত্সাহিত করে না), সুতরাং আমি এখানে চেষ্টা করেছি 10 টির মতো চেষ্টা করার পরে:

def add_helper(queue, arg1, arg2): # the func called in child processes
    ret = arg1 + arg2
    queue.put(ret)

def multi_add(): # spawns child processes
    q = Queue()
    processes = []
    rets = []
    for _ in range(0, 100):
        p = Process(target=add_helper, args=(q, 1, 2))
        processes.append(p)
        p.start()
    for p in processes:
        ret = q.get() # will block
        rets.append(ret)
    for p in processes:
        p.join()
    return rets

Queueহ'ল একটি ব্লকিং, থ্রেড-নিরাপদ সারি যা আপনি শিশু প্রক্রিয়াগুলি থেকে রিটার্ন মানগুলি সংরক্ষণ করতে ব্যবহার করতে পারেন। সুতরাং আপনি প্রতিটি প্রক্রিয়া সারি পাস করতে হবে। কিছু কম এখানে সুস্পষ্ট আপনি করতে হবে যে get()সারি থেকে আপনি আগে স্প্যানিশ ভাষায় বা অন্য কিউ fills আপ এবং ব্লক সবকিছু।joinProcess

যারা অবজেক্ট-ভিত্তিক তাদের জন্য আপডেট (পাইথন ৩.৪-তে পরীক্ষা করা হয়েছে):

from multiprocessing import Process, Queue

class Multiprocessor():

    def __init__(self):
        self.processes = []
        self.queue = Queue()

    @staticmethod
    def _wrapper(func, queue, args, kwargs):
        ret = func(*args, **kwargs)
        queue.put(ret)

    def run(self, func, *args, **kwargs):
        args2 = [func, self.queue, args, kwargs]
        p = Process(target=self._wrapper, args=args2)
        self.processes.append(p)
        p.start()

    def wait(self):
        rets = []
        for p in self.processes:
            ret = self.queue.get()
            rets.append(ret)
        for p in self.processes:
            p.join()
        return rets

# tester
if __name__ == "__main__":
    mp = Multiprocessor()
    num_proc = 64
    for _ in range(num_proc): # queue up multiple tasks running `sum`
        mp.run(sum, [1, 2, 3, 4, 5])
    ret = mp.wait() # get all results
    print(ret)
    assert len(ret) == num_proc and all(r == 15 for r in ret)

18

অন্য যে কেউ Processব্যবহারের মাধ্যমে কীভাবে কোনও মূল্য পেতে হয় তার জন্য Queue:

import multiprocessing

ret = {'foo': False}

def worker(queue):
    ret = queue.get()
    ret['foo'] = True
    queue.put(ret)

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    queue.put(ret)
    p = multiprocessing.Process(target=worker, args=(queue,))
    p.start()
    print queue.get()  # Prints {"foo": True}
    p.join()

1
যখন আমি আমার কর্মী প্রক্রিয়ায় একটি কাতারে কিছু রাখি তখন আমার যোগদান কখনই পৌঁছায় না। এটা কিভাবে আসতে পারে কোন ধারণা?
লরেন্স কোপ্পেনল

@ লরেন্সকপেনল মানে কি আপনার মূল কোডটি স্থায়ীভাবে p.join () এ স্থগিত হয়ে যায় এবং কখনও অব্যাহত থাকে না? আপনার প্রক্রিয়া একটি অসীম লুপ আছে?
ম্যাথু ময়েসেন

4
হ্যাঁ, এটি সেখানে অসীমভাবে ঝুলছে। আমার কর্মীরা সমস্ত শেষ (কর্মী ফাংশনের মধ্যে লুপ শেষ হয়, মুদ্রণ বিবৃতি পরে মুদ্রিত হয়, সমস্ত কর্মীদের জন্য)। যোগদানটি কিছুই করে না। যদি আমি Queueআমার ফাংশনটি থেকে সরিয়ে ফেলি তবে এটি আমাকে পাস করতে দেয়join()
লরেন্স কোপ্পেনল

@ লরেন্সকপেনল আপনি কি ডাকার queue.put(ret)আগে ডাকছেন না p.start()? সেক্ষেত্রে শ্রমিকের থ্রেড queue.get()চিরতরে ঝুলবে। আপনি মন্তব্য করার সময় উপরে আমার স্নিপেট অনুলিপি করে এটি প্রতিলিপি করতে পারেন queue.put(ret)
ম্যাথু মোইসেন

আমি এই উত্তরটি সম্পাদনা করেছি, এর queue.get()আগেই ঘটতে হবে p.join()। এটি এখন আমার জন্য কাজ করে।
jfunk

12

দেখে মনে হচ্ছে এর পরিবর্তে আপনার মাল্টিপ্রসেসিং.পুল ক্লাসটি ব্যবহার করা উচিত এবং পদ্ধতিগুলি প্রয়োগ করুন। অ্যাপ্লিকেশন ()। অ্যাপ্লিকেশন_সেনসি (), মানচিত্র ()

http://docs.python.org/library/multiprocessing.html?highlight=pool#multiprocessing.pool.AsyncResult


আমার কাছে টেনসরফ্লো কোড রয়েছে যার জন্য মাল্টিপ্রসেসিং.পুল হ্যাং করবে তবে মাল্টিপ্রসেসিং নয়
roপ্রসেস

10

exitকোনও প্রক্রিয়াটির প্রস্থান কোড সেট করতে আপনি অন্তর্নির্মিতটি ব্যবহার করতে পারেন । এটি exitcodeপ্রক্রিয়াটির বৈশিষ্ট্য থেকে পাওয়া যেতে পারে :

import multiprocessing

def worker(procnum):
    print str(procnum) + ' represent!'
    exit(procnum)

if __name__ == '__main__':
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        jobs.append(p)
        p.start()

    result = []
    for proc in jobs:
        proc.join()
        result.append(proc.exitcode)
    print result

আউটপুট:

0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[0, 1, 2, 3, 4]

4
সতর্ক হোন যে এই পদ্ধতির বিভ্রান্তি হতে পারে। প্রসেসগুলি সাধারণত প্রস্থান কোড 0 দিয়ে প্রস্থান করা উচিত সেগুলি ত্রুটি ছাড়াই সম্পন্ন হয়। আপনার সিস্টেম প্রসেসের প্রস্থান কোডগুলি পর্যবেক্ষণ করে যদি কিছু থাকে তবে আপনি এগুলিকে ত্রুটি হিসাবে দেখবেন।
লৌহঘটিত

1
আপনি যদি ত্রুটির ভিত্তিতে পিতামাতার প্রক্রিয়াতে কেবল ব্যতিক্রম বাড়াতে চান তবে পারফেক্ট।
ক্রিজক্রাইগ

5

নুড়ি প্যাকেজ একটা চমৎকার বিমূর্ততা উপজীব্য হয়েছে multiprocessing.Pipeযা এই বেশ সহজবোধ্য করে তোলে:

from pebble import concurrent

@concurrent.process
def function(arg, kwarg=0):
    return arg + kwarg

future = function(1, kwarg=1)

print(future.result())

এর থেকে উদাহরণ: https://pythonhosted.org/Pebble/#concurrent-decorators


3

ভেবেছি আমি উপরে থেকে অনুলিপি করা সহজ উদাহরণগুলি সহজ করে তুলব, আমার জন্য পাই 3.6 এ কাজ করে। সবচেয়ে সহজ multiprocessing.Pool:

import multiprocessing
import time

def worker(x):
    time.sleep(1)
    return x

pool = multiprocessing.Pool()
print(pool.map(worker, range(10)))

আপনি পুলটিতে প্রক্রিয়াগুলির সংখ্যা নির্ধারণ করতে পারেন, উদাহরণস্বরূপ Pool(processes=5),। তবে এটি সিপিইউ গণনায় ডিফল্ট, সুতরাং এটি সিপিইউ-বাউন্ড কাজের জন্য ফাঁকা রাখুন। (ইনপুট / আউটপুট-বাউন্ড কর্ম প্রায়ই মামলা থ্রেড যাহাই হউক না কেন, থ্রেড বেশিরভাগই তাই অপেক্ষা করছে একটি CPU- র কোর ভাগ করে নিতে পারেন।) Poolএছাড়াও প্রযোজ্য অপ্টিমাইজেশান কদর্য

(দ্রষ্টব্য যে কোনও পদ্ধতির মধ্যে কর্মী পদ্ধতিতে বাসা বেঁধে দেওয়া যায় না I আমি প্রথমে আমার কর্মী পদ্ধতিটিকে কলটি করে এমন পদ্ধতির অভ্যন্তরে সংজ্ঞায়িত করেছি pool.map, যাতে এটি সমস্ত স্বাবলম্বিত হয়, তবে প্রক্রিয়াগুলি এটিকে আমদানি করতে পারেনি এবং "এট্রিবিউটআরার" ছুঁড়ে ফেলেছে) : স্থানীয় অবজেক্টকে আউটআর_মোথাল..আনার_মোথডো আচার দেওয়া যায় না "আরও এখানে । এটি কোনও শ্রেণীর অভ্যন্তরে থাকতে পারে))

(এর 'represent!'পরিবর্তে মূল প্রশ্নটি নির্দিষ্ট করা মুদ্রণের প্রশংসা করুন time.sleep(), তবে এটি না করেই আমি ভেবেছিলাম কিছু কোড একযোগে চলছিল না যখন তা ছিল না))


পাই 3 এর ProcessPoolExecutorদুটি লাইনও রয়েছে ( .mapএকটি জেনারেটর ফেরত দেয় যাতে আপনার প্রয়োজন হয় list()):

from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
    print(list(executor.map(worker, range(10))))

সরল Processএস সহ:

import multiprocessing
import time

def worker(x, queue):
    time.sleep(1)
    queue.put(x)

queue = multiprocessing.SimpleQueue()
tasks = range(10)

for task in tasks:
    multiprocessing.Process(target=worker, args=(task, queue,)).start()

for _ in tasks:
    print(queue.get())

SimpleQueueআপনার প্রয়োজনীয় সমস্ত যদি putএবং হয় তবে ব্যবহার করুন get। প্রথম লুপটি সমস্ত প্রক্রিয়া শুরু করে, দ্বিতীয়টি ব্লকিং queue.getকল করার আগে। আমিও কল করার কোনও কারণ নেই বলে মনে করি p.join()না।


2

একটি সহজ সমাধান:

import multiprocessing

output=[]
data = range(0,10)

def f(x):
    return x**2

def handler():
    p = multiprocessing.Pool(64)
    r=p.map(f, data)
    return r

if __name__ == '__main__':
    output.append(handler())

print(output[0])

আউটপুট:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2

আপনি যদি পাইথন 3 ব্যবহার করেন তবে আপনি concurrent.futures.ProcessPoolExecutorসুবিধাজনক বিমূর্ততা হিসাবে ব্যবহার করতে পারেন :

from concurrent.futures import ProcessPoolExecutor

def worker(procnum):
    '''worker function'''
    print(str(procnum) + ' represent!')
    return procnum


if __name__ == '__main__':
    with ProcessPoolExecutor() as executor:
        print(list(executor.map(worker, range(5))))

আউটপুট:

0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[0, 1, 2, 3, 4]

0

আমি ফাংশন থেকে ত্রুটি কোডগুলি পাওয়ার জন্য যেহেতু আমি ভার্টেকের উত্তরটি কিছুটা পরিবর্তন করেছি। (ধন্যবাদ ভার্টেক !!! এটি একটি দুর্দান্ত কৌশল)

এটি একটি দিয়েও করা যেতে পারে manager.listতবে আমি মনে করি এটি একটি ডিকের মধ্যে থাকা এবং এটির মধ্যে একটি তালিকা সঞ্চয় করা ভাল। এইভাবে, আমরা ফাংশনটি রাখি এবং ফলাফলগুলি যেহেতু তালিকাটি ক্রমবর্ধমান হবে সে বিষয়ে আমরা নিশ্চিত হতে পারি না।

from multiprocessing import Process
import time
import datetime
import multiprocessing


def func1(fn, m_list):
    print 'func1: starting'
    time.sleep(1)
    m_list[fn] = "this is the first function"
    print 'func1: finishing'
    # return "func1"  # no need for return since Multiprocess doesnt return it =(

def func2(fn, m_list):
    print 'func2: starting'
    time.sleep(3)
    m_list[fn] = "this is function 2"
    print 'func2: finishing'
    # return "func2"

def func3(fn, m_list):
    print 'func3: starting'
    time.sleep(9)
    # if fail wont join the rest because it never populate the dict
    # or do a try/except to get something in return.
    raise ValueError("failed here")
    # if we want to get the error in the manager dict we can catch the error
    try:
        raise ValueError("failed here")
        m_list[fn] = "this is third"
    except:
        m_list[fn] = "this is third and it fail horrible"
        # print 'func3: finishing'
        # return "func3"


def runInParallel(*fns):  # * is to accept any input in list
    start_time = datetime.datetime.now()
    proc = []
    manager = multiprocessing.Manager()
    m_list = manager.dict()
    for fn in fns:
        # print fn
        # print dir(fn)
        p = Process(target=fn, name=fn.func_name, args=(fn, m_list))
        p.start()
        proc.append(p)
    for p in proc:
        p.join()  # 5 is the time out

    print datetime.datetime.now() - start_time
    return m_list, proc

if __name__ == '__main__':
    manager, proc = runInParallel(func1, func2, func3)
    # print dir(proc[0])
    # print proc[0]._name
    # print proc[0].name
    # print proc[0].exitcode

    # here you can check what did fail
    for i in proc:
        print i.name, i.exitcode  # name was set up in the Process line 53

    # here will only show the function that worked and where able to populate the 
    # manager dict
    for i, j in manager.items():
        print dir(i)  # things you can do to the function
        print i, j
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.