{"title":"Gestion du code asynchrone","version":"3.0","locale":"fr","docname":"topics/async","url":"/fr/3.0/topics/async/","canonical":"https://djangodocs.dev/fr/3.0/topics/async/","summary":"New in Django 3.0 Django a développé une prise en charge du code Python asynchrone (« async »), mais ne propose pas encore des vues ou des intergiciels asynchrones…","html":"<h1>Gestion du code asynchrone<a class=\"heading-anchor\" href=\"#asynchronous-support\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"version-note version-added\" data-version=\"3.0\">\n<p class=\"version-note-title\">New in Django 3.0</p></aside>\n<p>Django a développé une prise en charge du code Python asynchrone (« async »), mais ne propose pas encore des vues ou des intergiciels asynchrones ; cela devrait arriver dans les prochaines versions.</p>\n<p>Il existe une prise en charge restreinte pour d’autres parties de l’écosystème asynchrone ; en particulier, Django peut nativement converser avec <a class=\"reference internal\" href=\"/fr/3.0/howto/deployment/asgi/\"><span class=\"doc\">ASGI</span></a>, et apporte une prise en charge partielle de l’isolation de code asynchrone.</p>\n<section id=\"async-safety\">\n<span id=\"id1\"></span><h2>Isolation de code asynchrone<a class=\"heading-anchor\" href=\"#async-safety\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Certaines parties essentielles de Django ne sont pas capables d’opération de manière sûre dans un environnement asynchrone, car elles se basent sur un état global qui n’est pas compatible avec les coroutines. Ces parties de Django sont classées comme non sûres pour l’asynchrone (« async-unsafe ») et sont protégées contre l’exécution dans un environnement asynchrone. L’exemple principal est l’ORM (dialogue avec les bases de données), mais d’autres parties sont protégées de la même manière.</p>\n<p>Si vous essayez d’exécuter l’une de ces parties depuis un fil d’exécution où une <em>boucle événementielle s’exécute</em>, vous obtiendrez une erreur <a class=\"reference internal\" href=\"/fr/3.0/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation\" title=\"django.core.exceptions.SynchronousOnlyOperation\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">SynchronousOnlyOperation</span></code></a>. Notez que vous n’avez pas besoin d’être directement dans une fonction asynchrone pour déclencher cette erreur. Si vous avez appelé une fonction synchrone directement depuis une fonction asynchrone sans passer par un mécanisme comme <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code></a> ou un pool d’exécution, cela peut alors aussi arriver, car votre code se trouve encore dans un contexte asynchrone.</p>\n<p>SI vous obtenez cette erreur, vous devriez corriger votre code pour qu’il n’appelle pas le code de manière fautive depuis un contexte asynchrone ; ce peut être fait en plaçant le code communiquant avec la partie non prête pour l’asynchrone dans sa propre fonction synchrone et en l’appelant par <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">asgiref.sync.sync_to_async()</span></code></a>, ou toute autre méthode d’exécution de code synchrone dans un fil d’exécution adapté.</p>\n<p>Si vous avez un <em>impérieux</em> besoin d’appeler ce code depuis un contexte asynchrone, par exemple si un environnement externe vous force à le faire, et que vous êtes certain qu’il n’y a aucun risque qu’il soit lancé de manière concurrente (par ex. dans un carnet <a class=\"reference external\" href=\"https://jupyter.org/\">Jupyter</a>), vous pouvez désactiver l’avertissement avec la variable d’environnement <code class=\"docutils literal notranslate\"><span class=\"pre\">DJANGO_ALLOW_ASYNC_UNSAFE</span></code>.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Avertissement</p>\n<p>Si vous activez cette option et qu’un accès concurrent se produit sur des parties de Django non adaptées à l’asynchrone, vous pourriez expérimenter des pertes ou des corruptions de données. Soyez très prudent et n’utilisez pas cela dans des environnements de production.</p>\n</aside>\n<p>Si vous devez faire cela depuis du code Python, faites-le avec <code class=\"docutils literal notranslate\"><span class=\"pre\">os.environ</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"p\">[</span><span class=\"s2\">&quot;DJANGO_ALLOW_ASYNC_UNSAFE&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;true&quot;</span>\n</code></pre></div>\n</section>\n<section id=\"async-adapter-functions\">\n<h2>Fonctions d’adaptation asynchrone<a class=\"heading-anchor\" href=\"#async-adapter-functions\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Il est nécessaire d’adapter le style d’appel lors des appels de code synchrone depuis un contexte asynchrone ou vice versa. Il existe pour cela deux fonctions d’adaptation disponibles dans le paquet <code class=\"docutils literal notranslate\"><span class=\"pre\">asgiref.sync</span></code>: <a class=\"reference internal\" href=\"#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a> et <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code></a>. Elles sont utiles pour faire le passage entre des styles d’appel synchrones et asynchrones tout en préservant la compatibilité.</p>\n<p>Ces fonctions d’adaptation sont largement utilisées dans Django. Le paquet <a class=\"reference external\" href=\"https://pypi.org/project/asgiref/\">asgiref</a> lui-même fait partie du projet Django et il est automatiquement installé comme dépendance lorsqu’on installe Django avec <code class=\"docutils literal notranslate\"><span class=\"pre\">pip</span></code>.</p>\n<section id=\"async-to-sync\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code><a class=\"heading-anchor\" href=\"#async-to-sync\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"asgiref.sync.async_to_sync\">\n<span class=\"sig-name descname\"><span class=\"pre\">async_to_sync</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">async_function</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">force_new_loop</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#asgiref.sync.async_to_sync\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Enveloppe une fonction asynchrone et renvoie à la place une fonction synchrone. Peut être utilisée sous forme directe ou comme décorateur</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">async_to_sync</span>\n\n<span class=\"n\">sync_function</span> <span class=\"o\">=</span> <span class=\"n\">async_to_sync</span><span class=\"p\">(</span><span class=\"n\">async_function</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@async_to_sync</span>\n<span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">async_function</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>La fonction asynchrone est exécutée dans la boucle événementielle du fil d’exécution actuel, le cas échéant. S’il n’y a pas de boucle événementielle, un nouvelle boucle est générée spécifiquement pour la fonction asynchrone et arrêtée dès que la fonction est terminée. Quelle que soit la situation, la fonction asynchrone s’exécutera dans un fil d’exécution différent de celui du code appelant.</p>\n<p>Les valeurs « threadlocals » et « contextvars » sont préservées de part et d’autres des exécutions.</p>\n<p><a class=\"reference internal\" href=\"#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a> est fondamentalement une version plus puissante de la fonction <a class=\"reference external\" href=\"https://docs.python.org/3/library/asyncio-runner.html#asyncio.run\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code></a> de la bibliothèque Python standard. En plus de s’assurer du fonctionnement de « threadlocals », elle active aussi le mode <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code> de <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code></a> lorsque cette dernière est utilisée en dessous d’elle.</p>\n</section>\n<section id=\"sync-to-async\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code><a class=\"heading-anchor\" href=\"#sync-to-async\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"asgiref.sync.sync_to_async\">\n<span class=\"sig-name descname\"><span class=\"pre\">sync_to_async</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sync_function</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">thread_sensitive</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#asgiref.sync.sync_to_async\"><span class=\"visually-hidden\">Lien vers cette définition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Enveloppe une fonction synchrone et renvoie à la place une fonction asynchrone (utilisable avec <code class=\"docutils literal notranslate\"><span class=\"pre\">await</span></code>). Peut être utilisée sous forme directe ou comme décorateur</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">sync_to_async</span>\n\n<span class=\"n\">async_function</span> <span class=\"o\">=</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">sync_function</span><span class=\"p\">)</span>\n<span class=\"n\">async_function</span> <span class=\"o\">=</span> <span class=\"n\">sync_to_async</span><span class=\"p\">(</span><span class=\"n\">sensitive_sync_function</span><span class=\"p\">,</span> <span class=\"n\">thread_sensitive</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@sync_to_async</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">sync_function</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>Les valeurs « threadlocals » et « contextvars » sont préservées de part et d’autres des exécutions.</p>\n<p>Les fonctions synchrones ont tendances à être écrites en partant du principe qu’elles s’exécutent toutes dans le fil d’exécution principal, ce qui fait que <a class=\"reference internal\" href=\"#asgiref.sync.sync_to_async\" title=\"asgiref.sync.sync_to_async\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code></a> dispose de deux modes d’exécution :</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=False</span></code> (par défaut) : la fonction synchrone sera exécutée dans un tout nouveau fil d’exécution qui sera ensuite détruit lorsque la fonction sera terminée.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive=True</span></code>: la fonction synchrone sera exécutée dans le même fil d’exécution que toutes les autres fonctions <code class=\"docutils literal notranslate\"><span class=\"pre\">thread_sensitive</span></code>, et ce fil sera le fil principal si celui-ci est synchrone et que vous utilisez la fonction enveloppeuse <a class=\"reference internal\" href=\"#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a>.</p></li>\n</ul>\n<p>Le mode « thread-sensitive » est très spécial et fait beaucoup d’efforts pour exécuter toutes les fonctions dans le même fil d’exécution. Notez toutefois qu’il <em>compte sur l’utilisation de</em> <a class=\"reference internal\" href=\"#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a> <em>au-dessus de lui dans la pile d’appels</em> pour lancer les choses correctement dans le fil d’exécution principal. Si vous utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">asyncio.run()</span></code> (ou alors d’autres options), il se limite à exécuter simplement les fonctions dépendantes du fil d’exécution dans un seul fil partagé (mais pas le fil d’exécution principal).</p>\n<p>La raison de sa présence dans Django est que de nombreuses bibliothèques, particulièrement les adaptateurs de base de données, exigent que leur accès se fasse dans le même fil d’exécution dans lequel elles ont été créées ; une grande quantité de code existant dans Django présuppose qu’il s’exécute entièrement dans le même fil d’exécution (par ex. un intergiciel ajoutant des éléments à une requête pour utilisation ultérieure par une vue).</p>\n<p>Plutôt que d’introduire des problèmes potentiels de compatibilité avec ce code, nous avons choisi d’ajouter ce mode afin que tout code synchrone existant dans Django soit exécuté dans le même fil d’exécution et reste donc pleinement compatible avec le mode asynchrone. Notez que le code synchrone sera toujours exécuté dans un fil d’exécution <em>différent</em> du code asynchrone appelant, ce qui implique que vous devez éviter de passer des pointeurs bruts de base de données ou d’autres références sensibles au fil d’exécution dans tout nouveau code que vous écrivez.</p>\n</section>\n</section>","rootId":"asynchronous-support","toc":[{"title":"Isolation de code asynchrone","anchor":"async-safety","children":[]},{"title":"Fonctions d’adaptation asynchrone","anchor":"async-adapter-functions","children":[{"title":"async_to_sync()","anchor":"async-to-sync","children":[]},{"title":"sync_to_async()","anchor":"sync-to-async","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/3.0/topics/"}],"prev":{"docname":"topics/external-packages","title":"Paquets externes","url":"/fr/3.0/topics/external-packages/"},"next":{"docname":"howto/index","title":"Guides pratiques","url":"/fr/3.0/howto/"},"formats":{"html":"/fr/3.0/topics/async/","markdown":"/fr/3.0/topics/async.md","json":"/fr/3.0/topics/async.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/async.txt","official":"https://docs.djangoproject.com/fr/3.0/topics/async/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}