Differences between Futures in Python3 and Promises in ES6

Starting with Python 3.5, the await and async keywords are introduced into the language. Now I'm more of a Python 2.7 person, and I've been avoiding Python 3 for quite some time, so asyncio is pretty new to me. In my opinion, it looks like await/async works very similar to how they work in ES6 (or JavaScript, ES2015, but you want to call it.)

Here are two scenarios I made to compare them.

 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 event loop } main(); 

It should be noted that the codes are very similar, and they work almost the same.

Here are the questions:

  • In Python and ES6, await/async generator-based. Is it right to assume that futures are the same as Promises?

  • I saw the terms Task , Future and Coroutine used in the asyncio documentation. What are the differences between the two?

  • Should I start writing Python code that always runs an event loop?

+5
source share
2 answers
  • In Python and ES6, await/async generator-based. Is it right to consider futures the same as Promises?

Not Future , but Python Task roughly equivalent to Javascript Promise . See below for more details.

  1. I saw the terms Task , Future and Coroutine used in the asyncio documentation. What are the differences between the two?

These are completely different concepts. Basically Task consists of Future and Coroutine . Let's briefly describe these primitives (I'm going to simplify a lot of things to describe only the basic principles):

Future

The future is simply an abstraction of value that may not yet be calculated and will be available in the long run. This is a simple container that does only one thing - every time a value is set, start all registered callbacks.

If you want to get this value, you register a callback through the add_done_callback() method.

But unlike Promise , the actual calculation is done externally - and this external code must call the set_result() method to solve the future.

coroutine

Coroutine is an object very similar to Generator .

The generator is usually repeated in a for loop. It gives values ​​and, starting with PEP342 , it receives values.

A route is usually repeated inside an event loop in the depths of the asyncio library. Corutin gives instances of Future . When you iterate through a coroutine, and it gives the future, you must wait until that future is resolved. After that you will send value of the future in the coroutine, then you will get a different future, etc.

An await expression is almost identical to the yield from expression, therefore, waiting for another coroutine, you stop until this coroutine completes all its futures and receives the return value of coroutine. Future has an iteration of the same name, and its iterator returns the actual future - this roughly means that await future is equal to yield from future is equal to yield future .

Task

The "task of the future", which actually began to be calculated and tied to a cycle of events. Thus, a special kind of Future (the Task class is derived from the Future class), which is associated with some event loop, and it has some coroutine that serves as a task executor.

A task is usually created by an event loop object: you provide a coroutine for the loop, it creates a Task object and iterates over this coroutine in the manner described above. Once coroutine is complete, Task Future will be restored using the coroutine return value.

You see, the task is very similar to JS Promise - it encapsulates the background task and its result.

Coroutine Function and Async Function

The coroutine func function is a factory coroutine such as a generator function for generators. Note the difference between the Python coprocessor function and the async Javascript function. The async JS function creates Promise when called, and its internal generator starts iteration immediately, while the Pouton coroutine does nothing until Task is created on it.

  1. Should I start writing Python code that always has an event loop?

If you need any asynchronous function then you need. As it turned out, it's quite difficult to mix synchronous and asynchronous code - your whole program is better asynchronous (but you can run synchronous pieces of code in separate threads through the asyncio threadpool API)

+4
source

Ptyhon and ES6 are waiting / asynchronous, almost the same thing, a few details aside.

  • ES6, await / async are based on Promise Python: await / async are based on Futures . Generators have nothing to do with this.
  • In more detail, you will understand ... Coroutine is intended for parallel programming, and there are ways to describe the result of Coroutine as the Future.
  • Use an event loop when it makes sense (event driven server or gui)
-1
source

Source: https://habr.com/ru/post/1273657/


All Articles