खोज…


Coroutine और प्रत्यायोजन सिंटेक्स

पायथन 3.5+ जारी होने से पहले, asyncio मॉड्यूल ने एसिंक्रोनस कॉल की नकल करने के लिए जनरेटर का उपयोग किया था और इस प्रकार वर्तमान पायथन 3.5 रिलीज की तुलना में एक अलग वाक्यविन्यास था।

अजगर 3.x 3.5

पायथन 3.5 ने async और await खोजशब्दों को पेश किया। ध्यान दें कि await func() कॉल के आसपास कोष्ठक की कमी है।

import asyncio

async def main():
    print(await func())

async def func():
    # Do time intensive stuff...
    return "Hello, world!"

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
अजगर 3.x 3.3 3.5

पायथन 3.5 से पहले, @asyncio.coroutine डेकोरेटर का उपयोग एक @asyncio.coroutine को परिभाषित करने के लिए किया गया था। अभिव्यक्ति से उपज जनरेटर प्रतिनिधिमंडल के लिए इस्तेमाल किया गया था। yield from func() चारों ओर कोष्ठक पर ध्यान दें yield from func()

import asyncio

@asyncio.coroutine
def main():
    print((yield from func()))

@asyncio.coroutine
def func():
    # Do time intensive stuff..
    return "Hello, world!"

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
अजगर 3.x 3.5

यहां एक उदाहरण दिया गया है, जिसमें दिखाया गया है कि कैसे दो कार्यों को अतुल्यकालिक रूप से चलाया जा सकता है:

import asyncio

async def cor1():
    print("cor1 start")
    for i in range(10):
        await asyncio.sleep(1.5)
        print("cor1", i)

async def cor2():
    print("cor2 start")
    for i in range(15):
        await asyncio.sleep(1)
        print("cor2", i)

loop = asyncio.get_event_loop()
cors = asyncio.wait([cor1(), cor2()])
loop.run_until_complete(cors)

अतुल्यकालिक निष्पादनकर्ता

नोट: पायथन 3.5+ async / वेट सिंटैक्स का उपयोग करता है

asyncio का समर्थन करता है के उपयोग के Executor में पाया वस्तुओं concurrent.futures शेड्यूलिंग कार्यों एसिंक्रोनस रूप के लिए। घटना छोरों कार्य हो run_in_executor() जो एक लेता है Executor वस्तु, एक Callable , और प्रतिदेय के मानकों।

एक Executor लिए एक कार्य का समय निर्धारण

import asyncio
from concurrent.futures import ThreadPoolExecutor

def func(a, b):
    # Do time intensive stuff...
    return a + b

async def main(loop):
    executor = ThreadPoolExecutor()
    result = await loop.run_in_executor(executor, func, "Hello,", " world!")
    print(result)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

प्रत्येक ईवेंट लूप में एक "डिफ़ॉल्ट" Executor स्लॉट भी होता है जिसे Executor को सौंपा जा सकता है। एक निर्दिष्ट करने के लिए Executor पाश आप उपयोग से और अनुसूची कार्यों set_default_executor() विधि।

import asyncio
from concurrent.futures import ThreadPoolExecutor

def func(a, b):
    # Do time intensive stuff...
    return a + b

async def main(loop):
    # NOTE: Using `None` as the first parameter designates the `default` Executor.
    result = await loop.run_in_executor(None, func, "Hello,", " world!")
    print(result)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.set_default_executor(ThreadPoolExecutor())
    loop.run_until_complete(main(loop))

वहाँ के दो मुख्य प्रकार हैं Executor में concurrent.futures , ThreadPoolExecutor और ProcessPoolExecutorThreadPoolExecutor में थ्रेड्स का एक पूल होता है जिसे या तो मैन्युफैक्चरर द्वारा थ्रेड की एक विशिष्ट संख्या में सेट किया जा सकता है या मशीन समय पर कोर की संख्या के लिए डिफॉल्ट हो सकता है। ThreadPoolExecutor थ्रेड्स के पूल का उपयोग करता है ताकि इसे सौंपे गए कार्यों को निष्पादित किया जा सके और आमतौर पर I / O बाउंड ऑपरेशंस के बजाय सीपीयू-बाउंड ऑपरेशंस में बेहतर है। इसके विपरीत ProcessPoolExecutor जो इसे सौंपे गए प्रत्येक कार्य के लिए एक नई प्रक्रिया ProcessPoolExecutor है। ProcessPoolExecutor केवल कार्यों और पैरामीटर picklable हैं ले जा सकते हैं। सबसे आम गैर-पिकलेबल कार्य वस्तुओं के तरीके हैं। यदि आप किसी ऑब्जेक्ट की विधि को किसी कार्य में Executor रूप में शेड्यूल करते हैं, तो आपको एक ThreadPoolExecutor उपयोग करना होगा।

UVLoop का उपयोग करना

uvloop लिए एक कार्यान्वयन है, जो asyncio.AbstractEventLoop पर आधारित है (नोडज द्वारा प्रयुक्त)। यह 99% asyncio सुविधाओं के asyncio है और पारंपरिक asyncio.EventLoop तुलना में बहुत तेज है। uvloop वर्तमान में विंडोज पर उपलब्ध नहीं है, इसे pip install uvloop साथ pip install uvloop

import asyncio
import uvloop

if __name__ == "__main__":
    asyncio.set_event_loop(uvloop.new_event_loop())
    # Do your stuff here ...

एक भी सेट करके घटना पाश कारखाने को बदल सकते हैं EventLoopPolicy में से एक के लिए uvloop

import asyncio
import uvloop

if __name__ == "__main__":
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    loop = asyncio.new_event_loop()

तुल्यकालन आदिम: घटना

संकल्पना

एक से अधिक coroutines के शेड्यूल को सिंक्रनाइज़ करने के लिए किसी Event का उपयोग करें।

सीधे शब्दों में कहें, एक घटना दौड़ की दौड़ में बंदूक की गोली की तरह है: यह धावकों को शुरुआती ब्लॉकों से दूर जाने देता है।

उदाहरण

import asyncio

# event trigger function
def trigger(event):
    print('EVENT SET')
    event.set()  # wake up coroutines waiting

# event consumers
async def consumer_a(event):
    consumer_name = 'Consumer A'
    print('{} waiting'.format(consumer_name))
    await event.wait()
    print('{} triggered'.format(consumer_name))

async def consumer_b(event):
    consumer_name = 'Consumer B'
    print('{} waiting'.format(consumer_name))
    await event.wait()
    print('{} triggered'.format(consumer_name))

# event
event = asyncio.Event()

# wrap coroutines in one future
main_future = asyncio.wait([consumer_a(event),
                            consumer_b(event)])

# event loop
event_loop = asyncio.get_event_loop()
event_loop.call_later(0.1, functools.partial(trigger, event))  # trigger event in 0.1 sec

# complete main_future
done, pending = event_loop.run_until_complete(main_future)

आउटपुट:

उपभोक्ता बी इंतजार कर रहा है
उपभोक्ता एक प्रतीक्षा
घटना सेट
उपभोक्ता बी ने ट्रिगर किया
उपभोक्ता ए ने ट्रिगर किया

एक साधारण वेबसैट

यहां हम एसिंको का उपयोग करके एक सरल इको वेबस्कैट asyncio । हम एक सर्वर से कनेक्ट करने और संदेश भेजने / प्राप्त करने के लिए कोरआउट्स को परिभाषित करते हैं। वेबस्कैट के संवाद main कोरआउट में चलते हैं, जो एक इवेंट लूप द्वारा चलाया जाता है। यह उदाहरण एक पूर्व पोस्ट से संशोधित है।

import asyncio
import aiohttp

session = aiohttp.ClientSession()                          # handles the context manager
class EchoWebsocket:
    
    async def connect(self):
        self.websocket = await session.ws_connect("wss://echo.websocket.org")
        
    async def send(self, message):
        self.websocket.send_str(message)

    async def receive(self):
        result = (await self.websocket.receive())
        return result.data

async def main():
    echo = EchoWebsocket()
    await echo.connect()
    await echo.send("Hello World!")
    print(await echo.receive())                            # "Hello World!"


if __name__ == '__main__':
    # The main loop
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Asyncio के बारे में आम धारणा

शायद asnycio बारे में सबसे आम गलतफहमी यह है कि यह आपको समानांतर में किसी भी कार्य को चलाने देता है - GIL (वैश्विक दुभाषिया लॉक) को asnycio और इसलिए समानांतर (अलग थ्रेड पर) में अवरुद्ध नौकरियों को निष्पादित करता है। यह नहीं है !

asyncio (और पुस्तकालयों कि asyncio के साथ सहयोग करने के लिए बनाया गया है) coroutines पर निर्माण: कार्य है कि (सहयोगी) नियंत्रण प्रवाह वापस बुला समारोह में उपज। उपरोक्त उदाहरणों में asyncio.sleep ध्यान दें। यह एक गैर-अवरोधक कोरटाइन का एक उदाहरण है जो 'पृष्ठभूमि में' प्रतीक्षा करता है और कॉलिंग फ़ंक्शन (जब await साथ कहा जाता है) पर नियंत्रण प्रवाह देता है। time.sleep एक अवरुद्ध फ़ंक्शन का एक उदाहरण है। कार्यक्रम का निष्पादन प्रवाह बस वहीं रुक जाएगा और केवल समय के बाद वापस आ जाएगा। time.sleep समाप्त हो गया है।

एक वास्तविक-जीवंत उदाहरण requests पुस्तकालय है जिसमें केवल अवरुद्ध कार्यों पर (समय के लिए) समाहित है। यदि आप asyncio भीतर इसके किसी भी कार्य को कहते हैं, तो कोई संगामिति नहीं है। aiohttp दूसरी तरफ से बनाया गया था asyncio दिमाग में। इसके कोरआउट समवर्ती रूप से चलेंगे।

  • यदि आपके पास लंबे समय से सीपीयू-बाउंड कार्य हैं, तो आप समानांतर asyncio में चलाना चाहते हैं जो आपके लिए नहीं है। इसके लिए आपको threads या multiprocessing आवश्यकता है।

  • यदि आपके पास IO- बाउंड जॉब्स हैं, तो आप उन्हें asyncio का उपयोग करके समवर्ती रूप से चला सकते हैं।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow