如何在Twisted Klein中异步执行代码?

JLT*_*hiu 7 python asynchronous web-services twisted klein-mvc

我的python Twisted Klein Web服务中有两个函数:

@inlineCallbacks
def logging(data):
    ofile = open("file", "w")
    ofile.write(data)
    yield os.system("command to upload the written file")

@APP.route('/dostuff')
@inlineCallbacks
def dostuff():
    yield logging(data)
    print "check!" 
    returnValue("42")
Run Code Online (Sandbox Code Playgroud)

os.system("command to upload the written file")运行时,它会显示消息说"开始上传",然后"上传完成".我想使日志记录功能异步,以便在logging处理dostuff程序打印出"check!" 之后处理器中的处理.(我实际上希望在returnValue("42")之后进行处理,但是我认为这两者都使得日志记录功能异步?)

我认为yield语句会使它无阻塞,但似乎并非如此,"检查!" 始终在"开始上传"和"上传完成"后打印.我很感激,如果有人可以给我一些反馈意见,因为我是异步编码的新手并且暂时被阻止了...

Paw*_*ech 4

要使代码异步,您需要使用Twisted Deferreds,如此处所述。Deferreds 为您提供了用于异步代码执行的 API,它们允许您将回调附加到函数,并在由reactor对象管理的 Twisted 事件循环中执行代码。

我发现在您的情况下有两种使用 Deferreds 的潜在方法。

1)在后台执行任务reactor.callLater()

dostuff如果处理程序不关心结果,这是可以的。您可以使用reactor.callLater()。这样,您的异步函数将在您从 中返回值后执行doStuff

所以像这样:

from klein import run, route, Klein
from twisted.internet import defer, task, reactor
import os

app = Klein()


def logging(data):
    ofile = open("file", "w")
    ofile.write(data)
    result = os.system("ls")
    print(result)


@route('/')
def dostuff(request):
    reactor.callLater(0, logging, "some data")
    print("check!")
    return b'Hello, world!'

run("localhost", 8080)
Run Code Online (Sandbox Code Playgroud)

此代码的事件顺序如下,首先打印“check”,然后返回“hello world”响应,最后异步调用成功并打印运行结果os.system()

2016-08-11 08:52:33+0200 [-] check!
2016-08-11 08:52:33+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:52:32 +0000] "GET / HTTP/1.1" 200 13 "-" "curl/7.35.0"
a.py  file
Run Code Online (Sandbox Code Playgroud)

2)在后台执行任务并获取结果task.deferLater()

如果您关心“日志记录”功能的结果,您还可以将回调附加到该对象并使用twisted.internet.task API。如果你想这样做,你需要重构你的处理程序以像这样工作

@route('/')
def dostuff(request):
    def the_end(result):
        print("executed at the end with result: {}".format(result))
    dfd = task.deferLater(reactor, 0, logging, "some data")
    dfd.addCallback(the_end)
    print("check!")
    return b'Hello, world!'
Run Code Online (Sandbox Code Playgroud)

这样事件的顺序将与上面相同,但the_end函数将在函数完成后最后执行logging

2016-08-11 08:59:24+0200 [-] check!
2016-08-11 08:59:24+0200 [-] "127.0.0.1" - - [11/Aug/2016:06:59:23 +0000] "GET / HTTP/1.1" 200 13 "-" "curl/7.35.0"
a.py  file
2016-08-11 08:59:24+0200 [-] executed at the end with result: some result
Run Code Online (Sandbox Code Playgroud)