I'm getting the flow of using asyncio
in Python 3.5 but I haven't seen a description of what things I should be await
ing and things I should not be or where it would be neglible. Do I just have to use my best judgement in terms of "this is an IO operation and thus should be await
ed"?
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
You do not have much freedom. If you need to call a function you need to find out if this is a usual function or a coroutine. You must use the
await
keyword if and only if the function you are calling is a coroutine.If
async
functions are involved there should be an "event loop" which orchestrates theseasync
functions. Strictly speaking it's not necessary, you can "manually" run theasync
method sending values to it, but probably you don't want to do it. The event loop keeps track of not-yet-finished coroutines and chooses the next one to continue running.asyncio
module provides an implementation of event loop, but this is not the only possible implementation.Consider these two lines of code:
and
Semantic is absolutely the same: call a method which produces some value, when the value is ready assign it to variable
x
and do something else. In both cases thedo_something_else
function will be called only after the previous line of code is finished. It doesn't even mean that before or after or during the execution of asynchronousaget_x
method the control will be yielded to event loop.Still there are some differences:
async
functionaget_x
function is not usual, but coroutine (that is either declared withasync
keyword or decorated as coroutine)aget_x
is able to "communicate" with the event loop: that is yield some objects to it. The event loop should be able to interpret these objects as requests to do some operations (f.e. to send a network request and wait for response, or just suspend this coroutine forn
seconds). Usualget_x
function is not able to communicate with event loop.By default all your code is synchronous. You can make it asynchronous defining functions with
async def
and "calling" this functions withawait
. More correct question is "When should I write asynchronous code instead of synchronous?". Answer is "When you can benefit of it". In most cases as you noted you will get benefit, when you work with I/O operations:Of course, if you created function that uses asynchronous code, this function should be asynchronous too (should be defined as
async def
). But any asynchronous function can freely use synchronous code. It makes no sense to cast synchronous code to asynchronous without some reason:One very important thing is that any long synchronous operation (> 50 ms, for example, it's hard to say exactly) will freeze all your asynchronous operations for that time:
You can avoid it calling long running synchronous functions in separate process (and awaiting for result):
One more example: when you need to use
requests
in asyncio.requests.get
is just synchronous long running function, which you shouldn't call inside async code (again, to avoid freezing). But it's running long because of I/O, not because of long calculations. In that case, you can useThreadPoolExecutor
instead ofProcessPoolExecutor
to avoid some multiprocessing overhead: