title: Asyncio vs. Gevent
body: <h2>Background</h2>
  
  <p>I once worked on a Python2 system that had a lot of custom I/O code written synchronously, and was scaled using threads. At some point, we couldn't scale it any further, and realised we have to switch to asynchronous programming.</p>
  
  <ul>
  <li><a href="https://twistedmatrix.com/trac/" rel="noreferrer">Twisted</a> was the popular choice, but we wanted to avoid its callback hell.</li>
  <li>It did have the <a href="https://twistedmatrix.com/documents/13.2.0/api/twisted.internet.defer.inlineCallbacks.html" rel="noreferrer"><code>@inlineCallbacks</code></a> decorator, which effectively implemented coroutines using generator magic, as did some other libraries. That was more tolerable, but felt a bit flaky.</li>
  <li>And then we found <a href="http://www.gevent.org/" rel="noreferrer">gevent</a>. All you had to do was:</li>
  </ul>
  
  <pre><code>from gevent import monkey
  monkey.patch_all()
  </code></pre>
  
  <p>And just like that, all your standard I/O - sockets, database transactions, everything written in pure Python, really - was asynchronous, yielding and switching behind the scenes using greenlets.</p>
  
  <p>It wasn't perfect:</p>
  
  <ul>
  <li>Back then, it didn't work well on Windows (and it still has some limitations today). Luckily, we were running on Linux.</li>
  <li>It couldn't monkey-patch C extensions, so we couldn't use MySQLdb, for example. Luckily, there were many pure Python alternatives, like PyMySQL.</li>
  </ul>
  
  <h2>Question</h2>
  
  <p>Nowadays, Python 3 is much more popular, and with it - <a href="https://docs.python.org/3/library/asyncio.html" rel="noreferrer">asyncio</a>. Personally, I think it's great, but I was recently asked in what ways does it differ from what we implemented with gevent, and couldn't come up with a good enough answer.</p>
  
  <p>This might sound subjective, but I'm actually looking for <strong>real use-cases</strong> where one would significantly outperform the other, or allow something that the other does not. Here are the considerations I've gathered so far:</p>
  
  <ol>
  <li><p>Like I said, gevent is rather limited on Windows. Then again, most production code I know of runs on Linux.</p>
  
  <p><strong>If you need to run on Windows, use asyncio</strong>.</p></li>
  <li><p>Gevent can't monkey-patch C extensions. But, asyncio can't monkey-patch <em>anything</em>.</p>
  
  <p>Imagine that a new DB technology comes up, and you'd like to use it, but there's isn't a pure Python library for it, so you can't integrate it with Gevent. The thing is, you're just as stuck when there isn't an io* library that you can integrate with asyncio! There are worker threads and executors, of course, but that's not the point, and works just as well in both cases anyway.</p></li>
  <li><p>Some people say it's a matter of personal taste, but I think it's fair to say that synchronous programming is inherently easier that asynchronous programming (think about it: have you ever met a novice programmer that can work with sockets, but has a hard time understanding how to properly select/poll them, or thinking in futures/promises? And have you ever met the reverse?).</p>
  
  <p>Anyway, let's not go there. I wanted to address this point because it comes up frequently (<a href="https://www.reddit.com/r/Python/comments/7a3ikv/should_i_stick_with_asyncio_or_return_to_gevent/" rel="noreferrer">here's</a> a discussion on reddit), but what I'm really after is scenarios where you have a <em>practical</em> reason to use one or the other.</p></li>
  <li><p>Asyncio is part of the standard library. That's huge: it means it's well maintained, well documented, and everybody knows about it and uses it by default.</p>
  
  <p>But, considering how little of Gevent you need to know to use it (and that it's pretty well maintained and documented as well), it doesn't seem as crucial. So while there are multiple answers on StackOverflow for even the most complicated scenarios involving futures, the possibility to not use futures at all seems just as viable.</p></li>
  </ol>
  
  <p>Surely Guido and the Python community had a good reason to put so much effort into Asyncio, and even introduce new keywords into the languages - I just can't seem to find them.</p>
  
  <p><strong>What are the key differences between the two and in what scenarios do the become apparent?</strong></p>