2015-12-17 22 views
11

Dưới đây là một ví dụ đồ chơi mà tải các trang từ một số trang web sử dụng asyncio và aiohttp:Làm thế nào để không chờ đợi trong một vòng lặp với asyncio?

import asyncio 
import aiohttp 

sites = [ 
    "http://google.com", 
    "http://reddit.com", 
    "http://wikipedia.com", 
    "http://afpy.org", 
    "http://httpbin.org", 
    "http://stackoverflow.com", 
    "http://reddit.com" 
] 


async def main(sites): 
    for site in sites: 
     download(site) 


async def download(site): 
    response = await client.get(site) 
    content = await response.read() 
    print(site, len(content)) 


loop = asyncio.get_event_loop() 
client = aiohttp.ClientSession(loop=loop) 
content = loop.run_until_complete(main(sites)) 
client.close() 

Nếu tôi chạy nó, tôi nhận được:

RuntimeWarning: coroutine 'download' was never awaited 

Nhưng tôi không muốn chờ đợi nó.

Trong xoắn tôi có thể làm:

for site in sites: 
    download(site) 

Và Nếu tôi làm không rõ ràng "năng suất" hoặc thêm một callback để trở hoãn lại, nó chỉ chạy mà không cần chặn cũng không phàn nàn. Tôi không thể truy cập kết quả, nhưng trong trường hợp này tôi không cần nó.

Trong JS Tôi có thể làm:

site.forEarch(site){ 
    donwload(site) 
} 

Và một lần nữa, nó không chặn cũng không đòi hỏi bất cứ điều gì từ một phần của tôi.

Tôi tìm thấy một cách để làm:

async def main(sites): 
    await asyncio.wait([download(site) for site in sites]) 

Nhưng:

  • điều này thực sự không rõ ràng để tìm nó ra. Tôi rất khó nhớ.
  • thật khó để hiểu nó làm gì. "chờ đợi" dường như nói "tôi chặn", nhưng không truyền tải rõ ràng nó chặn cho toàn bộ danh sách coroutine kết thúc.
  • bạn không thể vượt qua trong một máy phát điện, nó cần phải được một danh sách thực sự, mà tôi cảm thấy thực sự không tự nhiên trong Python.
  • nếu tôi chỉ có ONE chờ đợi?
  • điều gì sẽ xảy ra nếu tôi không muốn chờ chút nào trong các nhiệm vụ của mình và chỉ cần lên lịch để thực hiện sau đó tiếp tục với phần còn lại của mã?
  • đó là cách giải pháp xoắn và giải mã JS chi tiết hơn.

Có cách nào tốt hơn không?

Trả lời

-1
  • điều này thực sự không rõ ràng để tìm ra. Tôi rất khó nhớ.

Các tài liệu trên coroutines không làm cho nó khá rõ ràng những gì asyncio.wait 's mục đích là.

  • thật khó để hiểu nó làm gì. "chờ đợi" dường như nói "tôi chặn", nhưng không truyền tải rõ ràng nó chặn cho toàn bộ danh sách coroutine kết thúc.

Một lần nữa, xem tài liệu.

  • bạn không thể chuyển qua trình tạo, nó cần phải là danh sách thực sự, điều tôi cảm thấy thực sự không tự nhiên trong Python.

Một lần nữa, xem tài liệu, đặc biệt là asyncio.as_completed

  • gì nếu tôi có chỉ ONE awaitable?

Nó vẫn hoạt động.

  • gì xảy ra nếu tôi không muốn đợi ở tất cả các nhiệm vụ của tôi, và chỉ cần lên lịch cho chúng để thực hiện sau đó tiếp tục với phần còn lại của mã của tôi?

Sau đó, bạn có thể sử dụng asyncio.ensure_furture. Thực tế, asyncio.wait là một chức năng tiện lợi xung quanh asyncio.ensure_future (và một số logic khác).

  • đó là cách giải mã xoắn và giải mã JS chi tiết hơn.

Có thể, nhưng đó không phải là điều xấu (theo quan điểm của tôi).

+1

Được chấp nhận và nâng cấp lên điều này sẽ giải quyết được sự cố của tôi. Tuy nhiên: các tài liệu không rõ ràng (ngay cả Guido cũng thừa nhận điều đó). Và phải đi đến các tài liệu cho một vấn đề đơn giản như vậy không phải là một dấu hiệu của thái tốt. Hơn nữa, có nhiều chi tiết hơn Twisted và JS, 2 công nghệ rất tiết là chắc chắn không phải là một huy hiệu danh dự. Đặc biệt kể từ khi rigth bây giờ bạn có thể chạy chỉ một eventloop, do đó, không sử dụng vòng lặp sự kiện mặc định tự động có vẻ quá mức cần thiết. Nhưng cảm ơn, đó là cách rõ ràng hơn bây giờ. –

+0

Đủ công bằng; nó có thể hiển nhiên đối với tôi bởi vì tôi đã sử dụng nó. Tôi chắc chắn có thể hiểu những người bị lạc trong tài liệu. Có quá nhiều phần. Tài liệu asyncio cần một hướng dẫn như hướng dẫn nhanh, giống như nhiều tài liệu của các mô-đun khác. –

+1

Tôi phải đồng ý với @ e-satis các tài liệu là khó khăn để làm theo. – medley56

5

Để sắp xếp một coroutine như một nhiệm vụ, sử dụng asyncio.ensure_future:

for site in sites: 
    coro = download(site) 
    future = asyncio.ensure_future(coro) 

Nó thay thế các chức năng phản asyncio.async trong phiên bản 3.4.4.

Sau đó, bạn có thể quản lý các tương lai đó bằng cách sử dụng await, asyncio.wait hoặc asyncio.gather.

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