Python Klein - 非阻塞 API

Posted

技术标签:

【中文标题】Python Klein - 非阻塞 API【英文标题】:Python Klein - Non Blocking API 【发布时间】:2019-10-18 18:07:58 【问题描述】:

在 Klein API for Non-blocking 方面需要帮助。 这是一个简单的测试应用:

# -*- coding: utf-8 -*-
import datetime
import json
import time
from klein import Klein

app = Klein()

async def delay(seconds):
    """Set some delay for test"""
    time.sleep(seconds)
    return "Works"

@app.route('/', branch=True)
async def main(request):
    some_data = await delay(5)

    return json.dumps([
        "status": "200",
        "time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "data": some_data
    ])

app.run("localhost", 8080)

然后只需运行我的server.py,然后同时向http://127.0.0.1:8080/ 发出2 个请求。 结果是:

[  "status": "200", "time": "2019-10-18 20:57:16", "data": "Works"  ]
[  "status": "200", "time": "2019-10-18 20:57:21", "data": "Works"  ]

每个响应之间有 5 秒的延迟。

问题:

如何让这段代码同时处理 2 个请求,现在它正在一个一个地工作......

也试过用twistd,结果一样

PYTHONPATH=. twistd --pidfile=apserver.pid -n web --class=api.resource --port tcp:8000:interface=0.0.0.0

谢谢

【问题讨论】:

嗨@Максим Дихтярь 如果这个或任何答案已经解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。 @Levon 是的,这有助于解决我的问题。非常感谢 【参考方案1】:

所以,问题在于您的 delay 函数 - 它是一个阻塞函数,因为 python 的 time.sleep - 正在阻塞。更多信息请阅读here。

你应该使用task.deferLater,你可以认为它是Twisted框架的非阻塞睡眠功能,类似于asyncio.sleep()

# app.py
import datetime
import json

import treq
from klein import Klein
from twisted.internet import task, reactor

app = Klein()

async def delay1(secs):
    await task.deferLater(reactor, secs)
    return "Works"

def delay2(secs):
    return task.deferLater(reactor, secs, lambda: "Works")

@app.route('/', branch=True)
async def main(request):
    some_data = await delay1(5)  # or some_data = await delay2(5) 

    return json.dumps([
        "status": "200",
        "time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "data": some_data
    ])

def send_requests():
    for i in range(2):
        print("request", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        d = treq.get('http://localhost:8080')
        d.addCallback(treq.content)
        d.addCallback(lambda x: print("response", x.decode()))

# send 2 concurrent requests every 10 seconds to test the code
repeating = task.LoopingCall(send_requests)
repeating.start(10, now=False)

app.run("localhost", 8080)

运行代码

$ pip3 install treq klein
$ python3 app.py

等待 10 秒,输出应该是

2019-10-21 17:17:11-0400 [-] request 2019-10-21 17:17:11
2019-10-21 17:17:11-0400 [-] request 2019-10-21 17:17:11
2019-10-21 17:17:16-0400 [-] "127.0.0.1" - - [21/Oct/2019:21:17:16 +0000] "GET / HTTP/1.1" 200 67 "-" "-"
2019-10-21 17:17:16-0400 [-] "127.0.0.1" - - [21/Oct/2019:21:17:16 +0000] "GET / HTTP/1.1" 200 67 "-" "-"
2019-10-21 17:17:16-0400 [-] response ["status": "200", "time": "2019-10-21 17:17:16", "data": "Works"]
2019-10-21 17:17:16-0400 [-] response ["status": "200", "time": "2019-10-21 17:17:16", "data": "Works"]

【讨论】:

以上是关于Python Klein - 非阻塞 API的主要内容,如果未能解决你的问题,请参考以下文章

阻塞-非阻塞 VS 同步-异步

同步异步阻塞非阻塞

Python web框架 Tornado异步非阻塞

Golang 阻塞和非阻塞

非阻塞socket总结

关于python中同步异步,阻塞非阻塞的理解