मैं यह क्रिस्टियन गार्सिया द्वारा ब्लॉग पोस्ट, और मैं एक बहुत ही दिलचस्प परिणाम में भाग गया।

यहां दो स्क्रिप्ट हैं जिनका मैंने उपयोग किया है। मैंने एक वास्तविक नेटवर्क अनुरोध को एक यादृच्छिक नींद कॉल के साथ बदल दिया

#task_pool.py
import asyncio

class TaskPool(object):

    def __init__(self, workers):
        self._semaphore = asyncio.Semaphore(workers)
        self._tasks = set()

    async def put(self, coro):
        await self._semaphore.acquire()
        task = asyncio.create_task(coro)
        self._tasks.add(task)
        task.add_done_callback(self._on_task_done)

    def _on_task_done(self, task):
        self._tasks.remove(task)
        self._semaphore.release()

    async def join(self):
        await asyncio.gather(*self._tasks)

    async def __aenter__(self):
        return self

    def __aexit__(self, exc_type, exc, tb):
        print("aexit triggered")
        return self.join()

और

# main.py
import asyncio
import sys
from task_pool import TaskPool
import random
limit = 3

async def fetch(i):
    timereq = random.randrange(5)
    print("request: {} start, delay: {}".format(i, timereq))
    await asyncio.sleep(timereq)
    print("request: {} end".format(i))
    return (timereq,i)

async def _main(total_requests):
    async with TaskPool(limit) as tasks:
        for i in range(total_requests):
            await tasks.put(fetch(i))

loop = asyncio.get_event_loop()
loop.run_until_complete(_main(int(sys.argv[1])))

कमांड main.py 10 अजगर 3.7.1 पर निम्नलिखित परिणाम देता है।

request: 0 start, delay: 3
request: 1 start, delay: 3
request: 2 start, delay: 3
request: 0 end
request: 1 end
request: 2 end
request: 3 start, delay: 4
request: 4 start, delay: 1
request: 5 start, delay: 0
request: 5 end
request: 6 start, delay: 1
request: 4 end
request: 6 end
request: 7 start, delay: 1
request: 8 start, delay: 4
request: 7 end
aexit triggered
request: 9 start, delay: 1
request: 9 end
request: 3 end
request: 8 end

इस परिणाम के आधार पर मेरे कुछ प्रश्न हैं।

  1. जब तक संदर्भ प्रबंधक बाहर नहीं निकलता और __aexit__ को ट्रिगर नहीं करता, तब तक मुझे कार्यों के चलने की उम्मीद नहीं थी, क्योंकि asyncio.gather के लिए यही एकमात्र ट्रिगर है। हालाँकि प्रिंट स्टेटमेंट दृढ़ता से सुझाव देते हैं कि fetch कार्य aexit से पहले भी हो रहे हैं। क्या हो रहा है, बिल्कुल? क्या कार्य चल रहे हैं? यदि हां, तो उन्हें क्या शुरू किया?
  2. (१) से संबंधित। सभी नौकरियों के वापस आने से पहले संदर्भ प्रबंधक बाहर क्यों निकल रहा है?
  3. fetch जॉब को टपल लौटाना चाहिए। मैं इस मूल्य तक कैसे पहुंच सकता हूं? वेब-आधारित एप्लिकेशन के लिए, मुझे लगता है कि डेवलपर वेबसाइट द्वारा लौटाए गए डेटा पर संचालन करना चाहता है।

कोई भी मदद बहुत ही सराहनीय होगी!

3
CuriousDan 30 नवम्बर 2018, 01:32

1 उत्तर

सबसे बढ़िया उत्तर
  1. create_task कहा जाता है।

    सीधे दस्तावेज़ीकरण से, पहली पंक्ति:

    कोरो कोरटाइन को टास्क में लपेटें और उसके निष्पादन को शेड्यूल करें।

  2. यह नहीं होना चाहिए, लेकिन। अपने प्रश्न में कोड देखें:

    def __aexit__(self, exc_type, exc, tb):
        print("aexit triggered")
        return self.join()
    

    तीन मुद्दे हैं:

    • यह एक नियमित सिंक्रोनस फ़ंक्शन है। इसे async def में बदलें और self.join() को लागू करने के लिए अनिवार्य await जोड़ें। यहां आप join को कॉल नहीं करते हैं, आप केवल कार्य बनाते हैं लेकिन इसे कभी नहीं चलाते हैं। आपका अजगर निश्चित रूप से शिकायत करता है कि आप कभी किसी कार्य की प्रतीक्षा नहीं करते हैं। उन चेतावनियों को कभी भी अनदेखा नहीं करना चाहिए क्योंकि उनका मतलब है कि आपके कार्यक्रम में कुछ बहुत गलत हो रहा है।

      [संपादित करें:] जैसा कि user4815162342 ने नीचे बताया है, आपके द्वारा लिखा गया निर्माण वास्तव में काम करेगा, हालांकि शायद इच्छित कारणों से नहीं - यह काम करता है क्योंकि self.join() को कॉल करके कोरआउटिन फ़ंक्शन वापस आ जाता है। प्रतीक्षा किए बिना इसे वापस कर दिया जाएगा और इसका उपयोग किया जाएगा जैसे कि यह स्वयं का था। आपको यह नहीं चाहिए, इसे एसिंक्स बनाएं और प्रतीक्षा करें।

    • एक बार यह ठीक हो जाने पर, __aexit__ "एक्जिट ट्रिगर" प्रिंट करेगा और फिर कॉल join करेगा, जो कार्यों के पूरा होने की प्रतीक्षा करता है। इसलिए अभी तक पूरे नहीं किए गए कार्यों के संदेश "एग्जिट ट्रिगर" संदेश के बाद दिखाई देंगे।

    • __aexit__ के रिटर्न वैल्यू को तब तक नजरअंदाज कर दिया जाता है, जब तक कि कोई अपवाद नहीं होने के कारण एग्जिट न हो जाए। उस स्थिति में, return True अपवाद को निगल जाएगा। return छोड़ें

    तो वह हिस्सा, तय:

    async def __aexit__(self, exc_type, exc, tb):
        print("aexit triggered")
        await self.join()
        print("aexit completed")
    
  3. आपके TaskPool को कार्यों का परिणाम उपलब्ध कराना होगा। यह डिजाइन करने के लिए आपका है, अजगर हुड के नीचे कोई जादू नहीं करेगा। आपके पास जो कुछ है, उससे join के लिए gather के परिणाम को कार्य पूल की विशेषता के रूप में संग्रहीत करने का एक आसान तरीका होगा।

2
spectras 1 पद 2018, 05:59