Site updated at 2016-12-06 08:23:42 UTC
This commit is contained in:
parent
9db92b7101
commit
d8f8521198
1358 changed files with 236897 additions and 220 deletions
284
developers/asyncio_categorizing_functions/index.html
Normal file
284
developers/asyncio_categorizing_functions/index.html
Normal file
|
@ -0,0 +1,284 @@
|
|||
<!doctype html>
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Categorizing Functions - Home Assistant</title>
|
||||
<meta name="author" content="Home Assistant">
|
||||
<meta name="description" content="A categorization of functions to work with the asynchronous core of Home Assistant.">
|
||||
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="canonical" href="https://home-assistant.io/developers/asyncio_categorizing_functions/">
|
||||
|
||||
<meta property="fb:app_id" content="338291289691179">
|
||||
<meta property="og:title" content="Categorizing Functions">
|
||||
<meta property="og:site_name" content="Home Assistant">
|
||||
<meta property="og:url" content="https://home-assistant.io/developers/asyncio_categorizing_functions/">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:description" content="A categorization of functions to work with the asynchronous core of Home Assistant.">
|
||||
<meta property="og:image" content="https://home-assistant.io/images/default-social.png">
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="@home_assistant">
|
||||
|
||||
<meta name="twitter:title" content="Categorizing Functions">
|
||||
<meta name="twitter:description" content="A categorization of functions to work with the asynchronous core of Home Assistant.">
|
||||
<meta name="twitter:image" content="https://home-assistant.io/images/default-social.png">
|
||||
|
||||
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet">
|
||||
<link href="/atom.xml" rel="alternate" title="Home Assistant" type="application/atom+xml">
|
||||
<link rel='shortcut icon' href='/images/favicon.ico' />
|
||||
<link rel='icon' type='image/png' href='/images/favicon-192x192.png' sizes='192x192' />
|
||||
</head>
|
||||
|
||||
<body >
|
||||
|
||||
<header>
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid">
|
||||
|
||||
<div class="grid__item three-tenths lap-two-sixths palm-one-whole ha-title">
|
||||
<a href="/" class="site-title">
|
||||
<img width='40' src='/demo/favicon-192x192.png'>
|
||||
<span>Home Assistant</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="grid__item seven-tenths lap-four-sixths palm-one-whole">
|
||||
<nav>
|
||||
<input type="checkbox" id="toggle">
|
||||
<label for="toggle" class="toggle" data-open="Main Menu" data-close="Close Menu"></label>
|
||||
<ul class="menu pull-right">
|
||||
|
||||
<li><a href="/getting-started/">Getting started</a></li>
|
||||
<li><a href="/components/">Components</a></li>
|
||||
<li><a href="/ecosystem/">Ecosystem</a></li>
|
||||
<li><a href="/cookbook/">Examples</a></li>
|
||||
<li><a href="/developers/">Developers</a></li>
|
||||
<li><a href="/blog/">Blog</a></li>
|
||||
<li><a href="/help/">Need help?</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid grid-center">
|
||||
|
||||
<div class="grid__item two-thirds lap-one-whole palm-one-whole">
|
||||
|
||||
|
||||
<article class="page">
|
||||
|
||||
|
||||
|
||||
|
||||
<header>
|
||||
<h1 class="title indent">
|
||||
Categorizing Functions
|
||||
</h1>
|
||||
</header>
|
||||
<hr class="divider">
|
||||
|
||||
|
||||
<p>A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe.</p>
|
||||
|
||||
<p>Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with <code class="highlighter-rouge">async_</code>.</p>
|
||||
|
||||
<h2><a class="title-link" name="the-coroutine-function" href="#the-coroutine-function"></a> The coroutine function</h2>
|
||||
|
||||
<p>Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result.</p>
|
||||
|
||||
<p>Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop.</p>
|
||||
|
||||
<p>To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function.</p>
|
||||
|
||||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">asyncio</span>
|
||||
|
||||
<span class="nd">@asyncio.coroutine</span>
|
||||
<span class="k">def</span> <span class="nf">async_look_my_coroutine</span><span class="p">(</span><span class="n">target</span><span class="p">):</span>
|
||||
<span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="k">from</span> <span class="n">entity</span><span class="o">.</span><span class="n">async_turn_on</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
||||
<span class="k">print</span><span class="p">(</span><span class="s">"hello {}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
||||
|
||||
<span class="n">hass</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">async_look_my_coroutine</span><span class="p">(</span><span class="s">"world"</span><span class="p">)</span>
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
<p>In this example, we schedule the coroutine by calling <code class="highlighter-rouge">hass.loop.create_task</code>. This will add the coroutine to the queue of tasks to be run. When the event loop is running <code class="highlighter-rouge">async_look_my_coroutine</code> it will suspend the task when <code class="highlighter-rouge">yield from entity.async_turn_on()</code> is called. At that point a new task will be scheduled to execute <code class="highlighter-rouge">entity.async_turn_on()</code>. When that job has been executed, <code class="highlighter-rouge">async_look_my_coroutine</code> will resume.</p>
|
||||
|
||||
<h2><a class="title-link" name="the-callback-function" href="#the-callback-function"></a> The callback function</h2>
|
||||
|
||||
<p>This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results.</p>
|
||||
|
||||
<p>To declare a function as a callback, import the callback annotation from the core package and annotate your function.</p>
|
||||
|
||||
<p>A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component.</p>
|
||||
|
||||
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">homeassistant.core</span> <span class="kn">import</span> <span class="n">callback</span>
|
||||
|
||||
<span class="nd">@callback</span>
|
||||
<span class="k">def</span> <span class="nf">async_trigger_service_handler</span><span class="p">(</span><span class="n">service_call</span><span class="p">):</span>
|
||||
<span class="s">"""Handle automation trigger service calls."""</span>
|
||||
<span class="nb">vars</span> <span class="o">=</span> <span class="n">service_call</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ATTR_VARIABLES</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">entity</span> <span class="ow">in</span> <span class="n">component</span><span class="o">.</span><span class="n">async_extract_from_service</span><span class="p">(</span><span class="n">service_call</span><span class="p">):</span>
|
||||
<span class="n">hass</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">create_task</span><span class="p">(</span><span class="n">entity</span><span class="o">.</span><span class="n">async_trigger</span><span class="p">(</span><span class="nb">vars</span><span class="p">,</span> <span class="bp">True</span><span class="p">))</span>
|
||||
</code></pre>
|
||||
</div>
|
||||
|
||||
<p>In this example, <code class="highlighter-rouge">entity.async_trigger</code> is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed.</p>
|
||||
|
||||
<p>To execute the task we have to schedule it for execution on the event loop. This is done by calling <code class="highlighter-rouge">hass.loop.create_task</code>.</p>
|
||||
|
||||
<h3><a class="title-link" name="why-even-have-callbacks" href="#why-even-have-callbacks"></a> Why even have callbacks?</h3>
|
||||
|
||||
<p>You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects.</p>
|
||||
|
||||
<p>When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine.</p>
|
||||
|
||||
<h2><a class="title-link" name="event-loop-and-thread-safe" href="#event-loop-and-thread-safe"></a> Event loop and thread safe</h2>
|
||||
|
||||
<p>These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries.</p>
|
||||
|
||||
<p>There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation.</p>
|
||||
|
||||
<h2><a class="title-link" name="other-functions" href="#other-functions"></a> Other functions</h2>
|
||||
|
||||
<p>These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O.</p>
|
||||
|
||||
<p>There is no special annotation necessary to be considered part of this category.</p>
|
||||
|
||||
<h3><a href="/developers/asyncio_working_with_async/">Next step: Working with Async »</a></h3>
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<aside id="sidebar" class="grid__item one-third lap-one-whole palm-one-whole">
|
||||
<div class="grid">
|
||||
|
||||
|
||||
<section class="aside-module grid__item one-whole lap-one-half">
|
||||
<div class='edit-github'><a href='https://github.com/home-assistant/home-assistant.github.io/tree/current/source/developers/asyncio_categorizing_functions.markdown'>Edit this page on GitHub</a></div>
|
||||
<div class='section'>
|
||||
<h1 class="title delta">Development Guide</h1>
|
||||
<ul class='divided sidebar-menu'>
|
||||
<li>
|
||||
<a href='/developers/'>Introduction </a>
|
||||
<ul>
|
||||
<li><a href='/developers/architecture/'>Architecture </a></li>
|
||||
<li><a href='/developers/architecture_components/'>Components </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/developers/development/'>Starting with Development </a>
|
||||
<ul>
|
||||
<li><a href='/developers/development_environment/'>Setting up Environment </a></li>
|
||||
<li><a href='/developers/development_submitting/'>Submit your Work </a></li>
|
||||
<li><a href='/developers/development_checklist/'>Checklist </a></li>
|
||||
<li><a href='/developers/development_testing/'>Testing </a></li>
|
||||
<li><a href='/developers/development_catching_up/'>Catching up with Reality </a></li>
|
||||
<li><a href='/developers/development_validation/'>Validation </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/developers/add_new_platform/'>Support a new device (as a platform) </a>
|
||||
<ul>
|
||||
<li><a href='/developers/platform_example_sensor/'>Example sensor platform </a></li>
|
||||
<li><a href='/developers/platform_example_light/'>Example light platform </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/developers/creating_components/'>Adding a new component </a>
|
||||
<ul>
|
||||
<li><a href='/developers/component_loading/'>Loading components </a></li>
|
||||
<li><a href='/developers/component_deps_and_reqs/'>Requirements & Dependencies </a></li>
|
||||
<li><a href='/developers/component_initialization/'>Initialization </a></li>
|
||||
<li><a href='/developers/component_events/'>Handling events </a></li>
|
||||
<li><a href='/developers/component_states/'>States </a></li>
|
||||
<li><a href='/developers/component_visibility/'>Visibility </a></li>
|
||||
<li><a href='/developers/component_generic_discovery/'>Loading Platforms </a></li>
|
||||
<li><a href='/developers/component_discovery/'>Component Discovery </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/developers/asyncio/'>Asynchronous Programming </a>
|
||||
<ul>
|
||||
<li><a class='active' href='/developers/asyncio_categorizing_functions/'>Categorizing Functions </a></li>
|
||||
<li><a href='/developers/asyncio_working_with_async/'>Working with Async </a></li>
|
||||
<li><a href='/developers/asyncio_misc/'>Miscellaneous </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href='/developers/frontend/'>Frontend Development </a>
|
||||
<ul>
|
||||
<li><a href='/developers/frontend_add_card/'>Add State Card </a></li>
|
||||
<li><a href='/developers/frontend_add_more_info/'>Add More Info Dialog </a></li>
|
||||
<li><a href='/developers/frontend_creating_custom_panels/'>Add Custom Panels </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
API
|
||||
<ul>
|
||||
<li><a href='https://dev-docs.home-assistant.io/en/dev/'>Home Assistant API </a></li>
|
||||
<li><a href='/developers/websocket_api/'>Websocket API </a></li>
|
||||
<li><a href='/developers/rest_api/'>RESTful API </a></li>
|
||||
<li><a href='/developers/python_api/'>Python API </a></li>
|
||||
<li><a href='/developers/server_sent_events/'>Server-sent events </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href='/developers/helpers/'>Online helpers </a></li>
|
||||
<li><a href='/developers/multiple_instances/'>Multiple Instances </a></li>
|
||||
<li><a href='/developers/website/'>Home-Assistant.io </a></li>
|
||||
<li><a href='/developers/credits/'>Credits </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="grid-wrapper">
|
||||
<div class="grid">
|
||||
<div class="grid__item">
|
||||
<div class="copyright">
|
||||
<a rel="me" href='https://twitter.com/home_assistant'><i class="icon-twitter"></i></a>
|
||||
<a rel="me" href='https://facebook.com/homeassistantio'><i class="icon-facebook"></i></a>
|
||||
<a rel="me" href='https://plus.google.com/110560654828510104551'><i class="icon-google-plus"></i></a>
|
||||
<a rel="me" href='https://github.com/home-assistant/home-assistant'><i class="icon-github"></i></a>
|
||||
|
||||
<div class="credit">
|
||||
Contact us at <a href='mailto:hello@home-assistant.io'>hello@home-assistant.io</a>.<br>
|
||||
Website powered by <a href='http://jekyllrb.com/'>Jekyll</a> and the <a href='https://github.com/coogie/oscailte'>Oscalite theme</a>.<br />
|
||||
Hosted by <a href='https://pages.github.com/'>GitHub</a> and served by <a href='https://cloudflare.com'>CloudFlare</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
var _gaq=[['_setAccount','UA-57927901-1'],['_trackPageview']];
|
||||
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
||||
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
|
||||
s.parentNode.insertBefore(g,s)}(document,'script'));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue