标签: asgi

Python asyncio跳过处理直到函数返回

我仍然对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库是同步的,但我想这是另一天的问题......

python python-asyncio python-3.7 quart asgi

6
推荐指数
1
解决办法
473
查看次数

如何配置 NGINX 以从 UNIX 套接字提供 ASGI?

我无法通过 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)

nginx supervisord gunicorn docker asgi

6
推荐指数
1
解决办法
3784
查看次数

Django 3.0 + Channels + ASGI + TokenAuthMiddleware

我升级到 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)

django django-channels asgi

6
推荐指数
1
解决办法
1449
查看次数

将当前使用 uWSGI Web 服务器的 Flask Web 应用程序迁移到 ASGI Web 服务器(uvicorn)

我现在有使用烧瓶Web应用程序uWSGI Web服务器,它实现了WSGI标准,需要这个应用程序迁移到uvicorn Web服务器实现了ASGI标准。

如果我从许多可用选项中选择使用 uvicorn Web 服务器,例如 Hypercorn、Daphne,那么我应该从可用选项中选择哪个 Web 微框架(而不是烧瓶),例如 Starlette、Quart、Django/Channels 来完成此迁移顺利?

层次结构是这样的:

  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.
Run Code Online (Sandbox Code Playgroud)

正如我到目前为止所读到的,

Quart 是一个基于 Asyncio 的 Python 网络微框架。它旨在提供在 Web 上下文中使用 asyncio 的最简单方法,尤其是在现有 Flask 应用程序中。

由于基于 Starlette 并由其提供支持,FastAPI 已被证明是具有最佳性能之一的 Python Web 框架,由第三方基准测试衡量。https://fastapi.tiangolo.com/benchmarks/

请用最好的方法提出建议

flask uwsgi asgi fastapi uvicorn

6
推荐指数
2
解决办法
6228
查看次数

带有 Django 频道的 heroku 的正确 procfile/要求是什么?

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 上。我不确定那里的使用说明是什么。最初的民意调查教程使用: …

django heroku django-channels daphne asgi

6
推荐指数
1
解决办法
1492
查看次数

使用 FastAPI 计算全局变量的请求数

我想统计特定 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”有含义吗?以及如何让它与多个工人一起工作?

python python-asyncio asgi fastapi uvicorn

6
推荐指数
2
解决办法
5095
查看次数

如何编写符合 ASGI 标准的中间件(同时保持与框架无关)?

我们目前正在维护用多个 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了该规范,难道不应该有一种方法来编写一个可以在两者中工作的中间件吗?

如果是的话,我错过了什么?

python asgi

6
推荐指数
1
解决办法
780
查看次数

FastAPI在通过其他Python应用程序调用时响应缓慢,但在cURL中响应速度很快

我有一个无法解决的问题。我有一个使用 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)

python windows python-requests asgi fastapi

6
推荐指数
1
解决办法
4167
查看次数

如何在 FastAPI 关闭时停止循环?

我有一条/开始无限循环的路线(从技术上讲,直到 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")应该在关闭期间调用,但怀疑它的调用类似于生命周期事件,该事件在一切完成后调用,在这种情况下这是一个死锁。

去测试:

  1. 我运行它作为uvicorn module.filename:app --host 0.0.0.0
  2. 卷曲 http://ip:端口/
  3. 然后停止服务器(按CTRL+C

你会看到它永远挂起,因为 running 永远不会设置为 false,因为shutdown_event没有被调用。(是的,您可以按 强制关机CTRL+C

python python-asyncio asgi fastapi

6
推荐指数
1
解决办法
3580
查看次数

Django Channels“关闭时间太长并被杀死”

我正在使用 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)

我很感激任何提示或提示。

最好的问候,丹尼斯

python django push-notification django-channels asgi

5
推荐指数
0
解决办法
935
查看次数