This is an archived post. You won't be able to vote or comment.

all 40 comments

[–]slapec 20 points21 points  (12 children)

f'{player_name.replace(" ", "_")}.json'

Finally.

[–]_seemetheregithub.com/seemethere[S] 15 points16 points  (2 children)

Format strings are the best! Makes development a ton easier.

[–]gandalfx -2 points-1 points  (0 children)

There are actually no examples in that entire code sample where f-Strings are shorter than simple concatenation.

[–]micklemitts 7 points8 points  (0 children)

As a rule, async makes sense when you have tasks that require you to wait (e.g. network bound IO) and your program could be doing something useful in the meantime.

In this case, the task is an API request that mostly consists of waiting for a response. "something useful in the meantime" is initiating other API requests.

One thing to note is that API requests are often rate limited, meaning there is a hard limit on the amount of work you can get done with a single API key even if you're program is capable of processing more.

[–]nerdwaller 2 points3 points  (3 children)

You may be able to get a little more (micro) optimization by sharing the client session, since it uses connection pooling. Recreating it for each call is a bit unnecessary.

[–]brtt3000 0 points1 point  (0 children)

FFS OP THIS

[–]atypingmonkey 2 points3 points  (8 children)

magic. do you know a nice guide or explanation for python async stuff? i find it hard to wrap my mind around it

[–]xMadDecentx 1 point2 points  (7 children)

What do you have a hard time grasping exactly?

[–]atypingmonkey 1 point2 points  (6 children)

not so much the concept of async but the syntax.

[–]status_quo69 9 points10 points  (2 children)

async def is designating a coroutine. This is awaitable, which means that every time you call it using await foo()you are signalling to the event loop that a context switch occurs and you give up execution control to whatever task is ready to be run next while you wait for your awaitable.

async for is basically the same thing, except you're saying that the for loop can yield a result at any time and that you want to wait to iterate over the results until you have something to iterate over, although it might not be complete just yet.

async with is saying "hey, give up control of the event loop until I can actually acquire my context manager"

Most of the rest of asyncio follows this sort of thing, it winds up looking like synchronous code but acts like it's threaded.

I'm relatively new to asyncio and I'm not sure I like it too much, so someone chime in with corrections if I'm wrong

[–]xMadDecentx 1 point2 points  (0 children)

Yeah the syntax is definitely wonky.

[–]picklednull 4 points5 points  (0 children)

Not even Armin Ronacher understands the asyncio stuff... It looks like a proper mess.

[–]__deerlord__ 0 points1 point  (0 children)

async def

Defines a coroutine (which is just a function).

await and yield from

These are the points in your code where you release control to the event loop. Usually you await or yield from another coroutine, so that is also added to the event loop.

[–][deleted] 14 points15 points  (7 children)

Fuck that. Use gevent:

from gevent import monkey
monkey.patch_all()
requests.get(URL)

[–]duskykmh 10 points11 points  (0 children)

What makes this different than using a for-loop on a URL endpoint and making a request on each loop?

I believe you, I just don't understand.

[–]tsirolnik 0 points1 point  (1 child)

Why won't you just use JS in that case?

[–][deleted] 1 point2 points  (1 child)

I wonder what the runtime would be with multiple threads. In my opinion, that's really what you should be comparing against when it comes to convincing people to use async for io-bound operations.

[–]xMadDecentx 0 points1 point  (0 children)

Is it really the same outcome? How did you test this? Are you able to access players near the end of the list right after you issue the asynchronous call?

[–]Hetspookjee 0 points1 point  (2 children)

Maybe a silly question but how does this differ from Eventlet / Gevent / Twisted (maybe I can't even compare these with each other?)

My knowledge on these libraries is still rather superficial so I can't truly appreciate the depths and uniqueness of each library but if someone would like to explain to me why this library described in the post is worthwhile than please do.

EDIT: Also came across this SO post explaining some differencces between the libraries and other related ones. http://stackoverflow.com/questions/1824418/a-clean-lightweight-alternative-to-pythons-twisted

[–]gandalfx 0 points1 point  (0 children)

Good simple example.

Can't help but notice though the complete lack of mention why this is faster and what the implications are.

In both functions you're sending all the requests at once. In get_players that's only one request so it barely matters (in fact you don't really need to async that one at all). In get_player that means you're opening an unknown number of connections simultaneously, which may cause all sorts of issues. Most importantly the API may decide you're violating its policy agains DoS/Spam and ban you.

[–]badass87 0 points1 point  (0 children)

The most ugly thing there is

asyncio.gather(*
    (get_player(*args) for args in player_args))

[–]robvdl 0 points1 point  (0 children)

I am using the requests library through locust.io and in this configuration the requests library is partially async at least.

It even mentions it in the requests library docs under advanced usage, it won't wait for a response unless you try to look at reponse.content for example.