python-在使用gevent的第一个函数完成后,如何生成另一个函数?

基本思想如下:

一个请求到达views1,它首先返回用户名.在完成views1之后,do_something_else会单独完成一些繁重的工作.您可以将其视为创建新用户,但是必须在后台进行大量检查.

def views1(..):
   username = get_uername(...)
   return username

from lib import do_something_else
def do_something_else(...):
   // do heavy stuff here

gevent.joinall([
   gevent.spawn(views1, parmeter1, parmeter2, ...),
   gevent.spawn(do_something_else, parmeter1, parmeter2, ...)
])

问题是我认为我的日志记录从未调用过do_something_else.
我阅读了教程,但不知道将gevent.sleep(0)放在哪里.我不想阻止.我希望用户立即看到用户名,并让do_something_else在后台运行.

任何想法?

解决方法:

重要的是要了解您需要将“重负载”处理分离到线程池中[1].

gevent线程中进行的每个处理(每个本机线程可以有一个gevent HUB)必须仅专注于处理网络请求和发送响应.

from gevent import spawn, run
from gevent.threadpool import ThreadPool
from time import sleep as heavy_load, time as now

class Globals:
    jobs = 4
    index = 0
    greenlets = []
    pool = ThreadPool(3) # change size of the pool appropriately

start = now()

def get_uername():
    heavy_load(0.1)
    Globals.index += 1
    return "Alex {0}".format(Globals.index)

def do_something_else(username):
    heavy_load(2.0)
    print "Heavy job done for", username, now() - start

def views1():
    "a request comes to views1 and it first returns the username"
    username = get_uername()
    ## There is some heavy job separate done by do_something_else right after views1 is done
    Globals.greenlets.append( 
        Globals.pool.spawn(do_something_else, username) 
        )
    # return username
    print "Returned requested username", username, now() - start


if __name__ == '__main__':
    ## simulate clients 
    for job_index in xrange(Globals.jobs):
        Globals.greenlets.append( spawn(views1) )

    ## wait for all tasks to complete
    # for greenlet in Globals.greenlets:
        # try:
            # greenlet.join()
        # except AttributeError, e:
            # greenlet.get()
    run()
    print "Test done", now() - start

这是测试的输出:

python threadpool_test.py
Returned requested username Alex 1 0.101000070572
Returned requested username Alex 2 0.201999902725
Returned requested username Alex 3 0.302999973297
Returned requested username Alex 4 0.40299987793
Heavy job done for Alex 1 2.10100007057
Heavy job done for Alex 2 2.2009999752
Heavy job done for Alex 3 2.3029999733
Heavy job done for Alex 4 4.10299992561
Test done 4.10500001907

请注意,首先如何完成所有请求,然后并行执行do_something_else任务(大小为3).

当不使用ThreadPool时,每个请求都将花费do_something_else引入的额外时间,并且这不是gevent必须提供的异步编程.在这种情况下,输出将如下所示:

Heavy job done for Alex 1 2.10100007057
Returned requested username Alex 1 2.10100007057
Heavy job done for Alex 2 4.2009999752
Returned requested username Alex 2 4.20199990273
Heavy job done for Alex 3 6.30200004578
Returned requested username Alex 3 6.3029999733
Heavy job done for Alex 4 8.40299987793
Returned requested username Alex 4 8.40400004387
Test done 8.40400004387

请注意,第4个请求是如何在8.4秒时完成的,而不是异步处理时的0.4秒.

[1] http://code.google.com/p/gevent/source/browse/examples/threadpool.py

上一篇:164 python网络编程 - 协程(gevent版)


下一篇:高效爬虫