简体   繁体   English

python中的异步函数调用

[英]Async function call in python

In python I want to create an async method in a class that create a thread without blocking the main thread. 在python中,我想在创建线程的类中创建一个异步方法而不会阻塞主线程。 When the new thread finish, I return a value from that function/thread. 新线程结束后,我从该函数/线程返回一个值。

For example the class is used for retrieve some information from web pages. 例如,该类用于从网页检索某些信息。 I want run parallel processing in a function that download the page and return a object. 我想在下载页面并返回对象的函数中运行并行处理。

class WebDown:
    def display(self, url):
        print 'display(): ' + content

    def download(self, url):
        thread = Thread(target=self.get_info)
        # thread join
        print 'download(): ' + content
        # return the info

    def get_info(self, url):
        # download page
        # retrieve info
        return info

if __name__ == '__main__':
    wd = WebDown()
    ret = wd.download('http://...')
    wd.display('http://...')

I this example, in order I call download() for retrieve the info, after display() for print others information. 在此示例中,为了在调用显示其他信息的display()之后,依次调用download()来检索信息。 The print output should be 打印输出应为

display(): foo, bar, ....
download(): blue, red, ....

One way to write asynchronous, non blocking code in python involves using Python's Twisted. 用python编写异步,非阻塞代码的一种方法涉及使用Python的Twisted。 Twisted does not rely on multithreading but uses multiprocessing instead . Twisted不依赖多线程,而是使用多处理 It gives you convenient way to create Deferred objects, adding callbacks and errbacks to them. 它为您提供了方便的方法来创建Deferred对象,并向它们添加回调和errbacks。 The example you give would look like this in Twisted, I'm using treq (Twisted Requests) library which makes generating requests a little quicker and easier: 您提供的示例在Twisted中看起来像这样,我使用的是treq (Twisted Requests)库,该库使生成请求更快,更轻松:

from treq import get
from twisted.internet import reactor

class WebAsync(object):
    def download(self, url):
        request = get(url)
        request.addCallback(self.deliver_body)

    def deliver_body(self, response):
        deferred = response.text()
        deferred.addCallback(self.display)
        return deferred

    def display(self, response_body):
        print response_body
        reactor.stop()

if __name__ == "__main__":
    web_client = WebAsync()
    web_client.download("http://httpbin.org/html")
    reactor.run()

Both 'download' and 'deliver_body' methods return deferreds , you add callbacks to them that are going to be executed when results is available. 'download'和'deliver_body'方法都返回deferred ,您将向它们添加回调,这些回调将在结果可用时执行。

I would simply use request and gevent called grequests . 我只是使用requestgevent叫做grequests

import grequests
>>> urls = [
    'http://...',
    'http://...'
]
>>> rs = (grequests.get(u) for u in urls)
>>> grequests.map(rs)
[<Response [200]>, <Response [200]>]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM