2017-06-28 15 views
13

मैं समझने की कोशिश कर रहा हूं कि एक प्रतीक्षा करने योग्य वस्तु कैसे बनाएं। documentation की परिभाषा बताती है:asyncio प्रतीक्षा करने योग्य वस्तु - मूल उदाहरण

एक ऑब्जेक्टर लौटने वाली __await__ विधि वाला एक ऑब्जेक्ट।

कि परिभाषा मैं नमूना कोड लिखा से प्रेरित होकर:

import asyncio 

async def produce_list(): 
     num = await Customer() 
     print(num) 

class Customer(object): 

    def __await__(self): 
     return iter([1, 2, 3, 4]) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(produce_list()) 

प्रवाह है कि मैं उम्मीद थी:

  1. घटना पाश produce_list() को नियंत्रण देता है। produce_list()num = await Customer() पर निष्पादन देता है।
  2. Customer() निष्पादित किया गया है और एक पुनरावर्तक लौटाता है। जो कि इटरेटर में पहला मान देता है। क्यू 1: यहां स्पष्ट नहीं है कि क्यों num इटेटरेटर नहीं बन रहा है। इसके अलावा send क्या कर रहा है?
  3. एक बार आखिरी मूल्य इटेटरेटर पहुंच गया है। num = 4 coroutine के निष्पादन print(num) जारी है, और मूल्य 4.

मुझे क्या मिला प्रिंट:

--------------------------------------------------------------------------- 
RuntimeError        Traceback (most recent call last) 
~/workspace/dashboard/so_question_await.py in <module>() 
    16 
    17 loop = asyncio.get_event_loop() 
---> 18 loop.run_until_complete(produce_list()) 

/usr/lib/python3.5/asyncio/base_events.py in run_until_complete(self, future) 
    464    raise RuntimeError('Event loop stopped before Future completed.') 
    465 
--> 466   return future.result() 
    467 
    468  def stop(self): 

/usr/lib/python3.5/asyncio/futures.py in result(self) 
    291    self._tb_logger = None 
    292   if self._exception is not None: 
--> 293    raise self._exception 
    294   return self._result 
    295 

/usr/lib/python3.5/asyncio/tasks.py in _step(***failed resolving arguments***) 
    239     result = coro.send(None) 
    240    else: 
--> 241     result = coro.throw(exc) 
    242   except StopIteration as exc: 
    243    self.set_result(exc.value) 

~/workspace/dashboard/so_question_await.py in produce_list() 
     5 
     6 async def produce_list(): 
----> 7   num = await Customer() 
     8   print(num) 
     9 

RuntimeError: Task got bad yield: 1 

क्या अवधारणाओं मैं गलत यहाँ मिल गया है?

अंत में मैं एक ऐसा उदाहरण ढूंढ रहा हूं जो कोरआउट के नियंत्रण में लौटने के लिए एक घटना के रूप में एक सूची के माध्यम से पुनरावृत्ति का उपयोग करता है।

उत्तर

4

__await__ एक पुनरावर्तक देता है क्योंकि कोरआउट के लिए अंतर्निहित तंत्र मूल रूप से yield from वाक्यविन्यास पर आधारित होता है। अभ्यास में, __await__ या तो iter(some_future) या some_coroutine.__await__() देता है। इसका उपयोग ऑब्जेक्ट्स बनाने के लिए किया जा सकता है जो हर बार अलग-अलग मूल्यों का उत्पादन करते हैं।

import asyncio 
import random 

class RandomProducer: 

    def __await__(self): 
     return self.producer().__await__() 

    async def producer(self): 
     sleep = random.random() 
     value = random.randint(0, 9) 
     return await asyncio.sleep(sleep, result=value) 

async def main(): 
    producer = RandomProducer() 
    while True: 
     print(await producer) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main()) 

अपनी टिप्पणी का जवाब करने के लिए:: asyncio.sleep बुला

अंत में समाप्त होता है हर coroutine क्या इसका सरल उदाहरण देखते हैं?

नहीं, और asyncio.sleep वास्तव में श्रृंखला का अंत नहीं है। बहुत नीचे, यह हमेशा एक भविष्य है जो पैदा किया जा रहा है: कोरआउट श्रृंखला घटना लूप से पूछती है "कृपया इस भविष्य के परिणामस्वरूप मुझे जगाएं"। asyncio.sleep के मामले में, यह किसी दिए गए समय के बाद भविष्य के परिणाम को सेट करने के लिए loop.call_later का उपयोग करता है। इस तरह के aiohttp रूप loop.call_at, loop.add_reader, loop.add_writer, loop.add_signal_handler, आदि

एक asyncio पुस्तकालय: पाश शेड्यूलिंग कॉलबैक के लिए और अधिक तरीकों प्रदान करता है। मुझे लगता है कि वहां कुछ कोड है जो पिछले कोरआउट के अस्तित्व पर भरोसा नहीं करता है।

सभी आईओ संचालन एकल-थ्रेडेड समेकन प्राप्त करने के लिए ईवेंट लूप को प्रतिनिधि को समाप्त करना होगा। उदाहरण के लिए, aiohttp loop.create_connection कोरआउट से manage the TCP connection पर निर्भर करता है।

+0

मैं वास्तव में एक उदाहरण प्राप्त करने की कोशिश कर रहा हूं कि अंत में पहले परिभाषित एसिन्सियो lib विधि को कॉल नहीं किया जाता है। अंत में आप 'इंतजार कर रहे हैं asyncio.sleep (नींद, परिणाम = मूल्य) '। प्रेरणा यह समझने की कोशिश करना है कि कोई एक नए एसिंसिओ फ्रेमवर्क के लेखन तक कैसे पहुंच जाएगा। – TheMeaningfulEngineer

+0

या शायद इसे फिर से भरना। क्या हर कोरआउट अंततः 'asyncio.sleep' को कॉल करता है? – TheMeaningfulEngineer

+0

@TheMeaningfulEngineer 'एक नए एसिन्सीओ फ्रेमवर्क के लेखन तक कैसे पहुंच जाएगा।' क्या आपका मतलब एसिन्सीओ लाइब्रेरी है जैसे [aiohttp] (http://aiohttp.readthedocs.io/en/stable/) या एसिन्सीओ विकल्प जैसे कि [curio] (https://github.com/dabeaz/curio)? इसके अलावा, मेरा संपादन देखें। – Vincent

संबंधित मुद्दे