2017-11-26 22 views
5

Kể từ Python 3.5, các từ khóa awaitasync được đưa vào ngôn ngữ. Bây giờ, tôi là một người Python 2.7 và tôi đã tránh Python 3 khá lâu nên asyncio khá mới mẻ đối với tôi. Theo hiểu biết của tôi, có vẻ như await/async hoạt động rất giống với cách chúng hoạt động trong ES6 (hoặc JavaScript, ES2015, tuy nhiên bạn muốn gọi nó.)Sự khác biệt giữa tương lai trong Python3 và lời hứa trong ES6

Dưới đây là hai kịch bản tôi đã thực hiện để so sánh chúng.

import asyncio 

async def countdown(n): 
    while n > 0: 
     print(n) 
     n -= 1 
     await asyncio.sleep(1) 

async def main(): 
    """Main, executed in an event loop""" 

    # Creates two countdowns 
    futures = asyncio.gather(
     countdown(3), 
     countdown(2) 
    ) 
    # Wait for all of them to finish 
    await futures 
    # Exit the app 
    loop.stop() 

loop = asyncio.get_event_loop() 
asyncio.ensure_future(main()) 
loop.run_forever() 
function sleep(n){ 
    // ES6 does not provide native sleep method with promise support 
    return new Promise(res => setTimeout(res, n * 1000)); 
} 

async function countdown(n){ 
    while(n > 0){ 
     console.log(n); 
     n -= 1; 
     await sleep(1); 
    } 
} 

async function main(){ 
    // Creates two promises 
    var promises = Promise.all([ 
     countdown(3), 
     countdown(2) 
    ]); 
    // Wait for all of them to finish 
    await promises; 
    // Cannot stop interpreter's event loop 
} 

main(); 

Một điều cần chú ý đó là các mã rất giống nhau và họ làm việc khá nhiều như nhau.

Dưới đây là những câu hỏi:

  1. Trong cả hai Python và ES6, await/async được dựa trên máy phát điện. Có đúng không khi nghĩ tương lai giống như lời hứa?

  2. Tôi đã thấy các điều khoản Task, FutureCoroutine được sử dụng trong tài liệu asyncio. Sự khác nhau giữa chúng là gì?

  3. Tôi có nên bắt đầu viết mã Python luôn có vòng lặp sự kiện đang chạy không?

Trả lời

3
  1. Trong cả hai Python và ES6, await/async được dựa trên máy phát điện. Có đúng không khi nghĩ tương lai giống như lời hứa?

Không Future, nhưng Python của Task là tương đương với Javascript của Promise. Xem thêm chi tiết bên dưới.

  1. Tôi đã thấy các điều khoản Task, FutureCoroutine sử dụng trong tài liệu asyncio. Sự khác nhau giữa chúng là gì?

Chúng là các khái niệm khá khác nhau. Chủ yếu, Task bao gồm FutureCoroutine.Hãy mô tả những nguyên thủy một thời gian ngắn (tôi sẽ đơn giản hóa rất nhiều điều để mô tả chỉ nguyên tắc chính):

Future

tương lai chỉ đơn giản là một sự trừu tượng của giá trị đó có thể không tính toán được nêu ra và sẽ có mặt cuối cùng . Đó là một container đơn giản mà chỉ làm một điều - bất cứ khi nào giá trị được đặt, kích hoạt tất cả các cuộc gọi lại đã đăng ký.

Nếu bạn muốn nhận được giá trị đó, bạn đăng ký gọi lại qua phương thức add_done_callback().

Nhưng không giống như trong Promise, tính toán thực tế được thực hiện bên ngoài - và mã bên ngoài đó phải gọi phương thức set_result() để giải quyết tương lai.

coroutine

coroutine là đối tượng rất giống với Generator.

Trình tạo thường được lặp lại trong vòng lặp for. Nó sản lượng giá trị và, bắt đầu từ PEP342 chấp nhận, nó nhận được giá trị.

Một coroutine thường được lặp lại trong vòng lặp sự kiện ở độ sâu của thư viện asyncio. Một coroutine mang lại Future trường hợp. Khi bạn đang lặp lại trên một coroutine và nó mang lại một tương lai, bạn sẽ đợi cho đến khi tương lai này được giải quyết. Sau đó bạn sẽ send giá trị của tương lai vào coroutine, sau đó bạn sẽ nhận được một tương lai khác, v.v.

Một biểu await là thực tế giống với yield from ngôn luận, như vậy theo chờ coroutine khác, bạn dừng lại cho đến coroutine có tất cả tương lai của mình được giải quyết, và nhận giá trị trả về coroutine của. Future là một lần đánh dấu có thể lặp lại và trình lặp của nó trả về Tương lai thực tế - điều đó có nghĩa là await future bằng yield from future bằng yield future.

công tác

nhiệm vụ là tương lai mà đã được thực sự bắt đầu để tính toán và được gắn vào vòng lặp sự kiện. Vì vậy, loại tương lai đặc biệt (lớp Task có nguồn gốc từ lớp Future), được liên kết với một số vòng lặp sự kiện và có một số coroutine, phục vụ như Task executor.

Tác vụ thường được tạo bởi đối tượng vòng lặp sự kiện: bạn cung cấp coroutine cho vòng lặp, nó tạo đối tượng Task và bắt đầu lặp qua coroutine theo cách được mô tả ở trên. Khi coroutine kết thúc, Task's Future được giải quyết bằng giá trị trả về của coroutine.

Bạn thấy đấy, nhiệm vụ khá giống với JS Promise - nó đóng gói công việc nền và kết quả của nó.

Chức năng coroutine và Chức năng Async

coroutine func là một nhà máy của coroutines, giống như chức năng máy phát điện để phát điện.Chú ý sự khác biệt giữa hàm coroutine của Python và hàm async của Javascript - Hàm async JS, khi được gọi, tạo ra một Promise và bộ tạo nội bộ của nó ngay lập tức bắt đầu được lặp lại, trong khi coroutine của Python không làm gì cả, cho đến khi Task được tạo ra trên nó.

  1. Tôi có nên bắt đầu viết mã Python luôn có vòng lặp sự kiện đang chạy không?

Nếu bạn cần bất kỳ tính năng asyncio nào thì bạn nên làm như vậy. Kết quả là chương trình của bạn tốt hơn không đồng bộ (nhưng bạn có thể khởi chạy các đoạn mã đồng bộ trong các luồng riêng biệt thông qua API asyncio threadpool)

+0

Đây là một câu trả lời tuyệt vời. –

-1

Ptyhon và ES6 await/async khá giống nhau, một vài chi tiết sang một bên.

  1. ES6, await/async được dựa trên Promise Python: await/async được dựa trên Futures. Máy phát điện không có gì để làm với điều này.
  2. Đọc thêm, bạn sẽ hiểu ... Coroutine, là để lập trình song song, và có nhiều cách để mô tả kết quả của Coroutine như một tương lai
  3. Sử dụng vòng lặp sự kiện khi có ý nghĩa (máy chủ điều khiển sự kiện hoặc gui)
Các vấn đề liên quan