Profile picture
, 65 tweets, 20 min read Read on Twitter
Here's @glasnt introducing @andrewgodwin's talk about adding async to Django @djangocon
@glasnt @andrewgodwin @djangocon "What are we here for? I can fit Django onto one slide and it is not Flask"

An async Django should look like a normal sync view but it runs asynchronously
@glasnt @andrewgodwin @djangocon "Python has threads; you can import threading... but it is a lie."

"It takes them and runs them in equal time slices no matter what."

"By comparison, coroutines are cooperative."

They only yield when they hit an await.

"Cooperative is part of the name."
@glasnt @andrewgodwin @djangocon "So we have these two different lands. Traditionally, people in Python have sometimes used threads."

In some ways, they're safer than threads, but they're harder to think about.
@glasnt @andrewgodwin @djangocon "The event loop is a thread. I had this dawning moment about two years ago: 'oh, this is awful' ... you can have multiple event loops. Don't do this."

"I can spin up an event loop and turn that sync thread into an async hosting thread."
@glasnt @andrewgodwin @djangocon "Then of course, you may want to synchronously call code like legacy python code... this gets tricky and we'll see how later."
@glasnt @andrewgodwin @djangocon "Why not just use threads? Threads are slow. As I mentioned, it's not a real OS level"

"As amber alluded, async is fast as long as you're I/O-bound. Luckily we write websites, and websites are pretty much I/O-bound full time"
@glasnt @andrewgodwin @djangocon "The other thing to consider is that while async may seem like a wonderful solution, there's a slight issue with the way Python has evolved... async functions are different to sync."

"You cannot have one function that you can call from a synchronous context and an async...
...context, and if you do it wrong, it's dangerous."
If you do a sync fetch in an async code, you "have ruined the contract of being cooperative" by blocking the entire event loop.
The bad way and the good way
"If you haven't gotten the impression yet, it's very dangerous."

"Asynchrony is great, but it should be an optional add-on."

"I love Django. Django is a big framework... it is very stable and predictable.
"Let's take caching. Caches are usually on the network. I have to do a connection, ask for the get, and it's usually tens of milliseconds... an eternity."

"We cannot have cache.get()" be sync and async.

It creates double the maintenance burden, too.
Also don't forget the vast library of third-party standards written for legacy sync code as well as the DB API which is entirely synchronous.

There's a separate time.sleep() vs asyncio.sleep()
"Standards are really good. One of the problems you have when you wanter into this new world and they're not there anymore"

WSGI: you can run flask, django, or 'the awful little app I wrote in a weekend' on it

In the old days, "this framework had to use this web server"
"I will not go into ASGI in full. That is another 45 minutes of presentation that would probably bore you all to death."

I'd be interested...
"Unlike WSGI where you're given the input when you're called, you can sit there and receive packets and send back packets"

It's more comms between client and server.
While we can do an async version of, say objects.get(), but we cannot do is async attribute access.
"Threads do matter. While most code is generally thread-safe, some things are not, and sqlite is one of them. Django and sqlite kind of come together like most suites are run in sqlite."

"We have to consider that async code is running in a thread and if you call async code...
... it runs in another thread."

Also have to consider backwards compat, which Django has tried to maintain since 1.0.

"And we have to keep that."
"We have to make sure all these features are accounted for"

"Async has to add to Django. We can't replace it."

"Things should look familiar and still feel Django-ish."

"Django should stop you from shooting yourself in the foot... DEBUG is one exception for that"
Django offers constant-time password checking, which is a useful defense against pw guessing
Here we go: diving into Django internals.

Simplified block diagram time: handler, middleware, ORM, URL router, view, template, forms
"This is sort of kind of useful because what we can do is take one of the key things I've learned about doing big rewrites, which is a phased approach."

Phase 1: talking to ASGI
Phase 2: making middleware+handler+view async
Phase 3: async ORM

"These three each have their own benefit. The first phase, ASGI support, is maybe the least useful to you, the end dev"
Some servers are already thinking about adding support beyond what we have now.

Django 3.0 has phase 1 and will launch in December.
Phase 2: async middleware will "almost certainly" hit Django 3.1
Phase 3 is "the largest, most difficult" part and will hopefully hit 3.2
Each phase brings concrete benefits even if we cancel

They can use lots of API async calls. Even if we only implement half the ORM, that's a huge perf boost
Fun fact: Django is older than WSGI, which turns out to actually help
He joined back in the 0.96 days. "Just so you know, Django is a smug, arrogant framework that doesn't play nice with others... or at least, that's the impression you'd get from reading the rants." @ubernostrum
@ubernostrum "It's one of the wonderful history things that have come full circle and lets us make things more easier."

"We have custom middleware. For those of you who weren't around in Python 10 years ago ... there was this wonderful grand version of WSGI middleware"
@ubernostrum How Django interacts with wagi
@ubernostrum argh, WSGI
@ubernostrum "You can take this whole idea and add in the ASGI side."
@ubernostrum Yay code reuse
@ubernostrum "It just sort of worked. It wasn't quite that easy, but it was fine."

"One of the nice things as well is that ASGI is deliberately mostly WSGI-compatible"

"There are some tricky parts. Uploaded files are particularly fun"
@ubernostrum "In Django, we have to take those chunks [of uploaded files] and write them" to a temporary memory storage (with disk backup)

"Thankfully, [calling async] is a danger you can understand and contain. What we have is a package called asgiref.sync.sync_to_async"
@ubernostrum "About half the Django sites I've seen shove requests into thread locals, so we have to handle that too. I know it's convenient, but -- it is fine."

"Think about Andrew did it and others and they have tests and it's probably fine."
@ubernostrum "Django 3.0 won't have async views, but it does set that groundwork and will let you write your own handler."

"The really good part is phase 2. I'm excited about this."
@ubernostrum Block diagram after phase two
@ubernostrum "You can handle thousands of concurrent connections without running OOM and exhausting threads with caveats that we will get to."

Also thanks to the test handler, "we are forever going to have sync code in the test client or handler calling into the new async base handler."
@ubernostrum WSGI support is not going away.

This means we have sync->async->sync, and "it leaves things in the request for things to do later blows up in the most spectacular fashion... I'm not going to tell you how I do it because it is awful."
@ubernostrum "There's a whole talk in this and you'll hate me for it"
@ubernostrum "Middleware is really annoying. The old style of Django middleware is great. You had a class, it had a process view and process response"
@ubernostrum The middleware lives on the stack
@ubernostrum "If you have just one sync middleware in the stack and all the middleware is sync, you have to use a thread."

"We're sure the only around this is to write all of Django middleware to be natively sync"
@ubernostrum Typo: natively async
@ubernostrum "Class-based views are a huge issue" because of the whole callable problem. "Templates are fun too. Templates are synchronous in Django. You may think if you raise a 500 error, or errors that get called at the top, there's a template handler that spins into action"
@ubernostrum "Tracebacks are worse."

"I have a branch where [async views] work and all but two tests pass, and that's why it's not in Django 3.0"
@ubernostrum "Then we get to the hard part which is the ORM. This is much less defined."

"Being Django-like is crucial. You have to have familiar but safe APIs."

"We can probably never have async traversing models, but you should probably use select_related() anyway."
@ubernostrum "Eventually we'll try to make the whole thing async and have a sync facade"

"We did add one thing in Django 3, which is the ORM is fully aware of async safety."

It raises errors if you try to access the ORM in an async context.
"I've never worked on the query...
...side of the ORM. It's slightly terrifying and scary in there."
"I want to stress this: we are not removing synchrony from Django. Some things just don't need to be async. ... I personally believe 80-90% of the site should be sync"

"Forms are perfectly fine" being sync.
"When we get to a point to where you can do `async def view()`... you can do a weekend project where you make an async request library or your own small async ORM and use it with Django."

"We have to be careful because performance is a concern."

TIL Django doesn't call...
...signals if there aren't any receivers.
"At this point, I have done 1.5 big rewrites of Django. I've experienced some burnout and it is not good... What I love about this project is it's a perfect example of where you can get involved with Django."

Suggests auth middleware as a first-time contribution.
"maybe some of you can learn the true horrors of async when you open the box."

Calls for funding because async expertise is rare.
"I don't want you [as a new contributor] to take a financial hit."
"This is maybe one of the largest changes in all of Django's history."

"The app magic removal was just when I entered Django."

"We haven't done one of these in a while... I need some way to talk to people... to have long conversations about weird async stuff."
Plug: forum.djangoproject.com

"Surely, Andrew, async is just a flash int he pan"

"There are a lot of things that have been buzzwords or just a flash in the pan... we live in a world where everything we do is I/O bound. I can't think of more than one site I've worked...
...on that was CPU-bound"

"It is my personal believe that a well-written async Django app could get a 5-10x improvement if it's heavily I/O bound"
"How many big sites are not just Django-bound?" Mentions calling other microservices, AWS/Google/Azure services, etc.
"Asynchrony comes directly back to UX."

"Django is there to give you the ability to write beautiful amazing websites that people love and you don't put too much effort."

Slides are coming on twitter momentarily.
The end. Questions in the hall or at sprints.

5 minute break before the next talk.
Missing some Tweet in this thread?
You can try to force a refresh.

Like this thread? Get email updates or save it to PDF!

Subscribe to Drew
Profile picture

Get real-time email alerts when new unrolls are available from this author!

This content may be removed anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!