我仍然对asyncio如何工作感到困惑,所以我试图设置一个简单的例子但是无法实现它.
以下示例是一个Web服务器(Quart),它接收生成大型PDF的请求,然后服务器在开始处理PDF之前返回响应,然后开始处理它,并稍后将下载链接发送到电子邮件.
from quart import Quart
import asyncio
import time
app = Quart(__name__)
@app.route('/')
async def pdf():
t1 = time.time()
await generatePdf()
return 'Time to execute : {} seconds'.format(time.time() - t1)
async def generatePdf():
await asyncio.sleep(5)
#sync generatepdf
#send pdf link to email
app.run()
Run Code Online (Sandbox Code Playgroud)
我该怎么做?在上面的例子中,我不希望在返回之前等待5秒.
我甚至不确定asyncio是否是我需要的.
我担心在响应返回后阻止服务器应用程序不是应该做的事情,但也不确定.
此外,pdf库是同步的,但我想这是另一天的问题......
我无法通过 docker 容器通过本地主机上 NGINX 上的 Unix 套接字连接在 ASGI + Gunicorn 上运行的应用程序。
假设我在 docker 容器中并运行 NGINX:
/usr/sbin/nginx
Run Code Online (Sandbox Code Playgroud)
我可以打开http://localhost/api/v1/items并从 NGINX 获得 404,这意味着它至少正在运行。
执行正在运行的 docker 服务,我可以使用以下命令启动 Gunicorn:
gunicorn app.main:app --name asgi --workers 3 --user=root --group=root --bind=unix:///tmp/asgi.sock --log-level=debug --log-file=- -k uvicorn.workers.UvicornWorker -c /gunicorn_conf.py
Run Code Online (Sandbox Code Playgroud)
Gunicorn 正确启动,使用另一个 exec,我可以卷曲我绑定的 UNIX 套接字并收到 200 响应。
curl --unix-socket ///tmp/asgi.sock http://localhost/api/v1/items
Run Code Online (Sandbox Code Playgroud)
我认为这意味着我在 NGINX 将流量定向到 http://localhost/api/v1/items 的配置中存在一些差异。
配置文件
daemon off;
user nginx;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
access_log /dev/stdout;
upstream asgi {
server unix:/tmp/asgi.sock …Run Code Online (Sandbox Code Playgroud) 我升级到 Django 3.0,现在使用 websockets + TokenAuthMiddleware 时出现此错误:
SynchronousOnlyOperation
You cannot call this from an async context - use a thread or sync_to_async.
Run Code Online (Sandbox Code Playgroud) 我现在有使用烧瓶Web应用程序uWSGI Web服务器,它实现了WSGI标准,需要这个应用程序迁移到uvicorn Web服务器实现了ASGI标准。
如果我从许多可用选项中选择使用 uvicorn Web 服务器,例如 Hypercorn、Daphne,那么我应该从可用选项中选择哪个 Web 微框架(而不是烧瓶),例如 Starlette、Quart、Django/Channels 来完成此迁移顺利?
层次结构是这样的:
Run Code Online (Sandbox Code Playgroud)Uvicorn: an ASGI server Starlette: (uses Uvicorn) a web microframework FastAPI: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc.
正如我到目前为止所读到的,
Quart 是一个基于 Asyncio 的 Python 网络微框架。它旨在提供在 Web 上下文中使用 asyncio 的最简单方法,尤其是在现有 Flask 应用程序中。
和
由于基于 Starlette 并由其提供支持,FastAPI 已被证明是具有最佳性能之一的 Python Web 框架,由第三方基准测试衡量。https://fastapi.tiangolo.com/benchmarks/
请用最好的方法提出建议
tl;dr - django 频道应用程序使用 manage.py runserver 在本地运行,但不在 heroku 上运行。
我是 django 频道的新手 - 尝试使用 heroku 频道部署一个非常基本的 django 应用程序。我最初使用标准django polls 教程构建了该项目并将其部署到 heroku。然后我使用django 频道教程添加了一个聊天应用程序。设法使用docker在本地运行良好,按照他们的建议和“python manage.py runserver”运行redis服务器。
我在尝试将其部署到 heroku 或使用 heroku local 在本地运行时遇到困难。我已经在 heroku 中添加了 redis 插件并修改了 settings.py 以指向 REDIS_URL 环境变量。如果合适,我还修改了我的模板以使用 wss(我认为这对 heroku 来说是必要的):
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
var target = ws_scheme + '://'
+ window.location.host
+ '/ws/chat/'
+ roomName
+ '/';
const chatSocket = new WebSocket(
target
);
...
Run Code Online (Sandbox Code Playgroud)
因此我得出的结论是问题出在 procfile 上。我不确定那里的使用说明是什么。最初的民意调查教程使用: …
我想统计特定 URL 路径中的请求数。
app = FastAPI()
counter = 0
@app.get("/do_something")
async def do_something():
global counter
counter += 1
return {"message": "Hello World"}
Run Code Online (Sandbox Code Playgroud)
这段代码可以吗?计数器应该是线程安全的?阿辛西奥安全吗?这是计算请求的正确方法(没有数据库)吗?在这种情况下,“do_something”函数中的“async”有含义吗?以及如何让它与多个工人一起工作?
我们目前正在维护用多个 HTTP 框架(Flask、aiohttp 和 FastAPI)编写的代码。重写它们以便它们都使用相同的框架目前是不可行的。我想在这些应用程序之间共享一些代码,这些代码非常适合中间件(日志记录配置、监控、身份验证等)。
最初的实现是通过子类化 Flask 来完成的,并且在所有基于 Flask 的应用程序中运行得非常好。但它在 aiohttp 或 FastAPI 中无法使用。
创建一个与框架无关的实现是可行的(理论上),今天早上我采用了一个更简单的案例,并成功地将其转换为 WSGI 中间件,并且能够将其集成到 Flask 应用程序中。
但 ASGI 给我带来了一些麻烦,因为没有太多关于纯 ASGI中间件的文档。所有示例都展示了如何为其框架编写中间件。
ASGI 官方文档在该主题上也非常“精简”。据我所知,它应该看起来像这样(附带问题:“传递给构造函数的第二个参数是什么?”):
class MyMiddleware:
def __init__(self, app, something) -> None:
self.app = app
self.something = something # <- what is this second argument?
async def __call__(self, scope, receive, send):
print("Hello from the Middleware")
await self.app(scope, receive, send)
Run Code Online (Sandbox Code Playgroud)
我以Starlette TimingMiddleware作为灵感,但我无法将它与aiohttp. 可能是因为他们的实现略有不同。
考虑到 ASGI 规范中有一个中间件部分,并且两者都aiohttp实现Starlette了该规范,难道不应该有一种方法来编写一个可以在两者中工作的中间件吗?
如果是的话,我错过了什么?
我有一个无法解决的问题。我有一个使用 FastAPI 构建的 API 服务,当我尝试从本地计算机上的另一个 Python 脚本调用任何端点时,响应需要 2 秒以上的时间。当我通过 cURL 或内置 Swagger 文档发送相同的请求时,响应几乎是即时的。
整个服务器脚本是这样的:
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Run Code Online (Sandbox Code Playgroud)
然后我使用 HTTPX 从测试脚本中调用它。我也尝试了 requests 包,结果是一样的。
import httpx
r = httpx.get('http://localhost:8000/')
print(r.elapsed)
Run Code Online (Sandbox Code Playgroud)
这会打印如下内容:0:00:02.069705
然后我使用 cURL 做同样的事情:
curl -w "@curl-format.txt" -o /dev/null -X 'GET' 'http://localhost:8000/'
Run Code Online (Sandbox Code Playgroud)
这打印:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left …Run Code Online (Sandbox Code Playgroud) 我有一条/开始无限循环的路线(从技术上讲,直到 Websocket 断开连接,但在这个简化的示例中,它确实是无限循环)。如何在关机时停止此循环:
from fastapi import FastAPI
import asyncio
app = FastAPI()
running = True
@app.on_event("shutdown")
def shutdown_event():
global running
running = False
@app.get("/")
async def index():
while running:
await asyncio.sleep(0.1)
Run Code Online (Sandbox Code Playgroud)
根据文档, @app.on_event("shutdown")应该在关闭期间调用,但怀疑它的调用类似于生命周期事件,该事件在一切完成后调用,在这种情况下这是一个死锁。
去测试:
uvicorn module.filename:app --host 0.0.0.0CTRL+C)你会看到它永远挂起,因为 running 永远不会设置为 false,因为shutdown_event没有被调用。(是的,您可以按 强制关机CTRL+C)
我正在使用 Django Channels 作为实时进度条。借助此进度条,客户可以获得模拟的实际反馈。此模拟可能需要超过 5 分钟,具体取决于数据大小。现在来说说问题。客户端可以成功启动模拟,但在此期间无法加载其他页面。此外,我收到以下错误消息:
Application instance <Task pending coro=<StaticFilesWrapper.__call__() running at /.../python3.7/site-packages/channels/staticfiles.py:44> wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/futures.py:348, <TaskWakeupMethWrapper object at 0x123aa88e8>()]>> for connection <WebRequest at 0x123ab7e10 method=GET uri=/2/ clientproto=HTTP/1.1> took too long to shut down and was killed.
Run Code Online (Sandbox Code Playgroud)
只有在模拟完成后,才能加载更多页面。
已经有关于这个主题的文章,但它们不包含任何适合我的解决方案。例如以下链接中的示例: https: //github.com/django/channels/issues/1119 这里的建议是降级 Channels 版本。但是,我遇到了其他错误,它也必须适用于较新的版本。
消费者、路由和asgi的代码完全按照说明中的要求实现:https://channels.readthedocs.io/en/stable/tutorial/index.html
需求.txt:
Django==3.1.2
channels==3.0.3
channels-redis==3.3.1
asgiref==3.2.10
daphne==3.0.2
Run Code Online (Sandbox Code Playgroud)
我很感激任何提示或提示。
最好的问候,丹尼斯