-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathCoroutines.html
More file actions
226 lines (205 loc) · 17.3 KB
/
Copy pathCoroutines.html
File metadata and controls
226 lines (205 loc) · 17.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Notes on Coroutines — Programming in Python 7.0 documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Threading and multiprocessing" href="ThreadingMultiprocessing.html" />
<link rel="prev" title="Asychronous Programming" href="Async.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" style="background: #4b2e83" >
<a href="../index.html">
<img src="../_static/UWPCE_logo_full.png" class="logo" alt="Logo"/>
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Topics in the Program</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../topics/01-setting_up/index.html">1. Setting up your Environment</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/02-basic_python/index.html">2. Basic Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/03-recursion_booleans/index.html">3. Booleans and Recursion</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/04-sequences_iteration/index.html">4. Sequences and Iteration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/05-text_handling/index.html">5. Basic Text Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/06-exceptions/index.html">6. Exception Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/07-unit_testing/index.html">7. Unit Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/08-dicts_sets/index.html">8. Dictionaries and Sets</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/09-files/index.html">9. File Handling</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/10-modules_packages/index.html">10. Modules and Packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/11-argument_passing/index.html">11. Advanced Argument Passing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/12-comprehensions/index.html">12. Comprehensions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/13-intro_oo/index.html">13. Intro to Object Oriented Programing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/14-magic_methods/index.html">14. Properties and Magic Methods</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/15-subclassing/index.html">15. Subclassing and Inheritance</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/16-multiple_inheritance/index.html">16. Multiple Inheritance</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/17-functional_programming/index.html">17. Introduction to Functional Programming</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topics/18-advanced_testing/index.html">18. Advanced Testing</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../topics/99-extras/index.html">19. Extra Topics</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="Pep8.html">Coding Style and Linting</a></li>
<li class="toctree-l2"><a class="reference internal" href="CodeReviews.html">Code Reviews</a></li>
<li class="toctree-l2"><a class="reference internal" href="PersistanceAndSerialization.html">Persistence and Serialization</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unicode.html">Unicode in Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="IteratorsAndGenerators.html">Iterators and Generators</a></li>
<li class="toctree-l2"><a class="reference internal" href="Decorators.html">Decorators</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/mailroom/mailroom-decorator.html">Mailroom – Decoratoring it</a></li>
<li class="toctree-l2"><a class="reference internal" href="ContextManagers.html">Context Managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/context-managers-exercise.html">A Couple Handy Context Managers</a></li>
<li class="toctree-l2"><a class="reference internal" href="MetaProgramming.html">Metaprogramming</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/mailroom/mailroom-meta.html">Mailroom – metaprogramming it!</a></li>
<li class="toctree-l2"><a class="reference internal" href="Logging.html">Logging and the logging module</a></li>
<li class="toctree-l2"><a class="reference internal" href="Debugging.html">Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="NoSQL.html">No SQL Databases</a></li>
<li class="toctree-l2"><a class="reference internal" href="GraphDatabases.html">Graph Databases</a></li>
<li class="toctree-l2"><a class="reference internal" href="Concurrency.html">Concurrent Programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="Async.html">Asychronous Programming</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Notes on Coroutines</a></li>
<li class="toctree-l2"><a class="reference internal" href="ThreadingMultiprocessing.html">Threading and multiprocessing</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exercises/threaded_downloader.html">Threaded Web Scraper</a></li>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html">Performance and Profiling</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" style="background: #4b2e83" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">Programming in Python</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content style-external-links">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home"></a> »</li>
<li><a href="../topics/99-extras/index.html"><span class="section-number">19. </span>Extra Topics</a> »</li>
<li>Notes on Coroutines</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/modules/Coroutines.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul><div class="rst-breadcrumbs-buttons" role="navigation" aria-label="Sequential page navigation">
<a href="Async.html" class="btn btn-neutral float-left" title="Asychronous Programming" accesskey="p"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="ThreadingMultiprocessing.html" class="btn btn-neutral float-right" title="Threading and multiprocessing" accesskey="n">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="notes-on-coroutines">
<span id="coroutines"></span><h1>Notes on Coroutines<a class="headerlink" href="#notes-on-coroutines" title="Permalink to this headline"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>These notes are incomplete, but maybe the first section is still useful?</p>
</div>
<p>Coroutines are a key feature required to do “proper” async programming in Python.</p>
<p>In practical use, coroutines are used in the context of an async framework that
provides handy utilities, and most importantly, an event loop to actually run the code.</p>
<p>But it’s helpful to play around a bit with coroutines on their own, to get a better understanding of what they really are, and how they work.</p>
<div class="section" id="what-is-a-coroutine">
<h2>What is a coroutine?<a class="headerlink" href="#what-is-a-coroutine" title="Permalink to this headline"></a></h2>
<p>Coroutines are functions that can hold state, and vary between invocations;
there can be multiple instances of a given coroutine at once.</p>
<p>This may sound a bit familiar from generators – a generator function can hold
state when it yields, and there can be multiple instances of the same generator
function at once.</p>
<p>The difference is that coroutines, in addition to holding state, can also return
control flow back to the system while they are holding that state.</p>
<p>Hopefully this will make a bit more sense after we’ve experimented a bit.</p>
</div>
<div class="section" id="coroutines-by-themselves">
<h2>Coroutines By Themselves<a class="headerlink" href="#coroutines-by-themselves" title="Permalink to this headline"></a></h2>
<p>Coroutines are really only useful when controlled by an event loop. And for the most part, you are going to use an event loop provided by an async framework, like the built in``asyncio`` package.</p>
<p>But it can be instructive to know about what is going on directly with coroutines, so we’ll experiment a bit here:</p>
<p>We can make a coroutine with the <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">def</span> <span class="nf">corout</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"running corout"</span><span class="p">)</span>
</pre></div>
</div>
<p>This, of course is a coroutine that does nothing but print a message. But let’s run it and see what happens:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [28]: </span><span class="n">corout</span><span class="p">()</span>
<span class="gh">Out[28]: </span><span class="go"><coroutine object corout at 0x1063ef6d0></span>
</pre></div>
</div>
<p>Hmm – nothing. The print statement didn’t happen. But what we got back is a “coroutine object”. So calling a coroutine function doesn’t run the code in the function, but rather creates a coroutine object and returns that. In fact, you can make any number of coroutine objects with the same “async def” function.</p>
<p>Why is that?</p>
<p>Recall from the definition of coroutines: “… that can hold state”. So you want to be able to create multiple instances of a coroutine, so each one can hold different state (again, very similar to generators).</p>
<p>So how do we actually run the code in the coroutine instance? First, we need to save it in a variable so we can refer to it, and then we can call its <code class="docutils literal notranslate"><span class="pre">send</span></code> method.</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [33]: </span><span class="n">cr</span> <span class="o">=</span> <span class="n">corout</span><span class="p">()</span>
<span class="gp">In [34]: </span><span class="nb">type</span><span class="p">(</span><span class="n">cr</span><span class="p">)</span>
<span class="gh">Out[34]: </span><span class="go">coroutine</span>
<span class="gp">In [35]: </span><span class="n">cr</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="go">running corout</span>
<span class="gt">---------------------------------------------------------------------------</span>
<span class="ne">StopIteration</span><span class="g g-Whitespace"> </span>Traceback (most recent call last)
<span class="nn"><ipython-input-35-72be8e65d115></span> in <span class="ni"><module></span><span class="nt">()</span>
<span class="ne">----> </span><span class="mi">1</span> <span class="n">cr</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="ne">StopIteration</span>:
</pre></div>
</div>
<p>So calling <code class="docutils literal notranslate"><span class="pre">send</span></code> ran the print statement, and then raised a <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exception. This is looking even more like a generator, isn’t it?</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [36]: </span><span class="k">def</span> <span class="nf">genfunction</span><span class="p">():</span>
<span class="go"> ...: print("in the generator")</span>
<span class="go"> ...: yield None</span>
<span class="go"> ...:</span>
<span class="gp">In [37]: </span><span class="n">g</span> <span class="o">=</span> <span class="n">genfunction</span><span class="p">()</span>
<span class="gp">In [38]: </span><span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="go">in the generator</span>
<span class="gp">In [39]: </span><span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="gt">---------------------------------------------------------------------------</span>
<span class="ne">StopIteration</span><span class="g g-Whitespace"> </span>Traceback (most recent call last)
<span class="nn"><ipython-input-39-5f315c5de15b></span> in <span class="ni"><module></span><span class="nt">()</span>
<span class="ne">----> </span><span class="mi">1</span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="ne">StopIteration</span>:
</pre></div>
</div>
<p>And indeed, they have a lot on common – in fact, before Python 3.5, when the <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword was added, you used generator functions to make coroutines.</p>
<p>But if a coroutine raises <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> right away, what’s the point? Well, recall that the point of a coroutine (and asnyc in general), is to be able to return control to the system, while you wait for something else to happen. And thus the “await” keyword. So a coroutine isn’t useful unless it uses <code class="docutils literal notranslate"><span class="pre">await</span></code></p>
<p><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">an_awaitable</span></code> suspends the coroutine until something is done, then returns the “awaitable“‘s result.</p>
<p>hmm – we have a trick here – we need an “awaitable” object – how do we get one of those? Well, a coroutine is awaitable, so let’s make the simplest one of those:</p>
</div>
</div>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="Async.html" class="btn btn-neutral float-left" title="Asychronous Programming" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="ThreadingMultiprocessing.html" class="btn btn-neutral float-right" title="Threading and multiprocessing" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>© Copyright 2020, University of Washington, Natasha Aleksandrova, Christopher Barker, Brian Dorsey, Cris Ewing, Christy Heaton, Jon Jacky, Maria McKinley, Andy Miles, Rick Riehle, Joseph Schilz, Joseph Sheedy, Hosung Song. Creative Commons Attribution-ShareAlike 4.0 license.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>