2016-05-17 34 views
5

Tôi có một mã chặn, không async như thế này:lặp Lazy (máy phát điện) với asyncio

def f(): 
    def inner(): 
     while True: 
      yield read() 
    return inner() 

Với mã này người gọi có thể chọn khi nào phải ngừng chức năng để tạo ra dữ liệu. Làm thế nào để thay đổi điều này thành không đồng bộ? Giải pháp này không hoạt động:

async def f(): 
    async def inner(): 
     while True: 
      yield await coroutine_read() 
    return inner() 

... vì không thể sử dụng trong các chức năng async def. Nếu tôi xóa số async khỏi chữ ký inner(), tôi không thể sử dụng await nữa.

+0

Bạn không cần 'yield read()' khi sử dụng asyncio, vì 'await' sẽ thực hiện chính xác điều này đằng sau hậu trường. Điều này không trả lời câu hỏi của khóa học. –

+1

PEP-0492 [không bao gồm] (https://www.python.org/dev/peps/pep-0492/#coroutine-generators) coroutine-máy phát điện (đó là những gì bạn muốn), vì vậy, kể từ khi PEP chỉ được thực hiện trong 3.5, tôi đoán câu trả lời là "không có cách nào để làm điều này". –

+1

Cố gắng triển khai cách tạo ra bên trong các hàm không đồng bộ: http://stackoverflow.com/a/37572657/1113207 –

Trả lời

5

Như đã lưu ý ở trên, bạn không thể sử dụng yield bên trong async funcs. Nếu bạn muốn tạo coroutine-generator bạn phải làm điều đó bằng tay, sử dụng __aiter____anext__ magic method:

import asyncio 


# `coroutine_read()` generates some data: 
i = 0 
async def coroutine_read(): 
    global i 
    i += 1 
    await asyncio.sleep(i) 
    return i 


# `f()` is asynchronous iterator. 
# Since we don't raise `StopAsyncIteration` 
# it works "like" `while True`, until we manually break. 
class f: 
    async def __aiter__(self): 
     return self 

    async def __anext__(self): 
     return await coroutine_read() 


# Use f() as asynchronous iterator with `async for`: 
async def main(): 
    async for i in f(): 
     print(i) 
     if i >= 3: 
      break 


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

Output:

1 
2 
3 
[Finished in 6.2s] 

Bạn cũng có thể muốn thấy other post, nơi StopAsyncIteration sử dụng.

UPD:

Bắt đầu với Python 3.6 chúng tôi có asynchronous generators và có khả năng sử dụng yield trực tiếp bên coroutines.

Các vấn đề liên quan