2016-10-10 11 views
20

Tôi đã đọc rất nhiều bài báo và hướng dẫn về điều 3.5 không đồng bộ/chờ đợi của Python. Tôi phải nói rằng tôi khá bối rối, bởi vì một số sử dụng get_event_loop() và run_until_complete(), một số sử dụng Ensure_future(), một số sử dụng asyncio.wait(), và một số sử dụng call_soon(). Có vẻ như tôi có rất nhiều lựa chọn, nhưng tôi không biết họ có hoàn toàn giống nhau hay không có trường hợp bạn sử dụng vòng lặp và có những trường hợp bạn sử dụng wait().Python 3.5 không đồng bộ/đang chờ với ví dụ mã thực

Nhưng vấn đề là tất cả các ví dụ đều hoạt động với asyncio.sleep() làm mô phỏng hoạt động chậm thực sự, trả về một đối tượng đang chờ. Một khi tôi cố gắng trao đổi dòng này cho một số mã thực sự toàn bộ điều thất bại. Sự khác nhau giữa các cách tiếp cận được viết ở trên là gì và tôi nên chạy thư viện của bên thứ ba chưa sẵn sàng cho async/await như thế nào. Tôi sử dụng dịch vụ Quandl để lấy một số dữ liệu chứng khoán.

import asyncio 
import quandl 

async def slow_operation(n): 
    # await asyncio.sleep(1) # Works because it's await ready. 
    await quandl.Dataset(n) # Doesn't work because it's not await ready. 


async def main(): 
    await asyncio.wait([ 
     slow_operation("SIX/US9884981013EUR4"), 
     slow_operation("SIX/US88160R1014EUR4"), 
    ]) 

# You don't have to use any code for 50 requests/day. 
quandl.ApiConfig.api_key = "MY_SECRET_CODE" 

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

Tôi hy vọng bạn nhận được điểm mất cảm giác và cách đơn giản tôi muốn chạy song song.

Trả lời

25

Nếu thư viện của bên thứ ba không tương thích với async/await thì rõ ràng bạn không thể sử dụng dễ dàng. Có hai trường hợp:

  1. Giả sử chức năng trong thư viện không đồng bộ và cung cấp cho bạn gọi lại, ví dụ:

    def fn(..., clb): 
        ... 
    

    Vì vậy, bạn có thể làm:

    def on_result(...): 
        ... 
    
    fn(..., on_result) 
    

    Trong trường hợp đó, bạn có thể quấn chức năng đó vào giao thức asyncio như thế này:

    from asyncio import Future 
    
    def wrapper(...): 
        future = Future() 
        def my_clb(...): 
         future.set_result(xyz) 
        fn(..., my_clb) 
        return future 
    

    (sử dụng future.set_exception(exc) về ngoại lệ)

    Sau đó, bạn có thể chỉ cần gọi trình bao bọc đó ở một số chức năng async với await:

    value = await wrapper(...) 
    

    Lưu ý rằng await làm việc với bất kỳ đối tượng Future. Bạn không phải khai báo wrapperasync.

  2. Nếu chức năng trong thư viện đồng bộ thì bạn có thể chạy nó trong một chuỗi riêng biệt (có thể bạn sẽ sử dụng một số nhóm chủ đề cho điều đó). Toàn bộ mã có thể trông như thế này:

    import asyncio 
    import time 
    from concurrent.futures import ThreadPoolExecutor 
    
    # Initialize 10 threads 
    THREAD_POOL = ThreadPoolExecutor(10) 
    
    def synchronous_handler(param1, ...): 
        # Do something synchronous 
        time.sleep(2) 
        return "foo" 
    
    # Somewhere else 
    async def main(): 
        loop = asyncio.get_event_loop() 
        futures = [ 
         loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), 
         loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), 
         loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), 
        ] 
        await asyncio.wait(futures) 
        for future in futures: 
         print(future.result()) 
    
    with THREAD_POOL: 
        loop = asyncio.get_event_loop() 
        loop.run_until_complete(main()) 
    

Nếu bạn không thể sử dụng chủ đề vì lý do gì sau đó sử dụng một thư viện như vậy chỉ đơn giản là làm cho toàn bộ mã không đồng bộ vô nghĩa.

Lưu ý rằng việc sử dụng thư viện đồng bộ với async có thể là một ý tưởng tồi. Bạn sẽ không nhận được nhiều và bạn có phức tạp mã rất nhiều.

+0

Cảm ơn bạn đã ngoại lệ. Tôi nhận được điểm nhưng bạn có thể viết mã đầy đủ trong ví dụ mã cuối cùng không? Cảm ơn bạn. – grafa

+1

@grafa Đây rồi. – freakish

+0

Cảm ơn bạn. Tôi có thể gọi trình bao bọc nhiều lần liên tiếp với các tham số khác nhau và nó được gọi song song không? – grafa

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