Reg*_*lva 23 asynchronous jupyter django-3.0
我使用 Django 3.0.6 和运行shell_plus --notebook.
我尝试运行查询集:
User.objects.all()
但是返回这个错误SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async。
我试试这个命令
from asgiref.sync import sync_to_async
users = sync_to_async(User.objects.all())
for user in users:
print(user)
TypeError: 'SyncToAsync' object is not iterable
Run Code Online (Sandbox Code Playgroud)
Django文档的解决方案
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true" 在 settings.py 中是唯一的解决方案吗?
Tom*_*ick 21
sync_to_async takes a callable, not the result. Instead, you want this:
from asgiref.sync import sync_to_async
users = sync_to_async(User.objects.all)()
for user in users:
print(user)
Run Code Online (Sandbox Code Playgroud)
You can also put the call(s) you want to wrap in a decorated function:
from asgiref.sync import sync_to_async
@sync_to_async
def get_all_users():
return User.objects.all()
for user in await get_all_users():
print(user)
Run Code Online (Sandbox Code Playgroud)
Note that this must be used from an async context, so a full example would look like:
from asgiref.sync import sync_to_async
@sync_to_async
def get_all_users():
return User.objects.all()
async def foo(request):
for user in await get_all_users():
print(user)
Run Code Online (Sandbox Code Playgroud)
lyh*_*543 18
出现错误是因为 Jupyter notebooks 有一个正在运行的事件循环。从文档
如果您尝试从存在正在运行的事件循环的线程中运行这些部分中的任何一个,您将收到 SynchronousOnlyOperation 错误。请注意,您不必直接在异步函数内即可发生此错误。如果您直接从异步函数调用同步函数,而没有通过诸如 sync_to_async() 或线程池之类的方法,那么它也可能发生,因为您的代码仍在异步上下文中运行。
如果遇到此错误,则应修复代码以不从异步上下文调用有问题的代码;相反,在它自己的同步函数中编写与 async-unsafe 对话的代码,并使用 asgiref.sync.sync_to_async() 或任何其他在其自己的线程中运行同步代码的首选方式来调用它。
如果您绝对迫切需要从异步上下文中运行此代码 - 例如,它是由外部环境强加给您的,并且您确定它不可能同时运行(例如您在 Jupyter 中) notebook),然后您可以使用 DJANGO_ALLOW_ASYNC_UNSAFE 环境变量禁用警告。
由于问题特定于 jupyter notebook 环境,因此以下是一个有效的解决方案。
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rest.settings')
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
django.setup()
from users.models import User
User.objects.all()
Run Code Online (Sandbox Code Playgroud)
但是需要谨慎,不要按照文档警告在生产环境中使用它。
小智 14
您无法在同步和异步函数之间传递查询集,因为它是惰性的。您需要在异步上下文中评估它。
像这样:
from django.contrib.auth.models import User
from asgiref.sync import sync_to_async
import asyncio
@sync_to_async
def get_users():
return list(
User.objects.all()
)
async def user_loop():
results = await get_users()
for r in results:
print(r.username)
loop = asyncio.get_event_loop()
loop.run_until_complete(user_loop())
Run Code Online (Sandbox Code Playgroud)
从文档
\n如果您尝试运行 Django 的任何非异步部分(例如 ORM),您将收到 SynchronousOnlyOperation 错误。请注意,您不必直接位于异步函数内才能发生此错误。如果您直接从异步函数调用同步函数,而不使用sync_to_async()或类似的方法,那么也可能会发生这种情况。这是因为您的代码仍在具有活动事件循环的线程中运行,即使它可能未声明为异步代码。
\n你应该使用:
\nfrom asgiref.sync import sync_to_async\n\ndef _get_blog(pk):\n return Blog.objects.get(pk=pk)\n\nget_blog = await sync_to_async(_get_blog, thread_sensitive=True)(10)\n\n....\n\nRun Code Online (Sandbox Code Playgroud)\n或者
\nfrom asgiref.sync import sync_to_async\n\nget_blog = await sync_to_async(Blog.objects.get, thread_sensitive=True)(10)\n\nRun Code Online (Sandbox Code Playgroud)\n您可以使用Django通道的database_sync_to_async,它是asgiref.sync的改进的sync_to_async函数
\n例如:
\nfrom channels.db import database_sync_to_async\n\nget_blog = await database_sync_to_async(Blog.objects.get, thread_sensitive=True)(10)\n\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
16269 次 |
| 最近记录: |