· 9 years ago · Oct 05, 2016, 05:34 AM
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Author: Yuande Liu <miraclecome (at) gmail.com>
4
5from __future__ import print_function, division
6
7from gevent import monkey; monkey.patch_all()
8import gevent
9import time
10
11
12def add_func(x):
13 x += 2
14 time.sleep(0.5)
15 print('add result: ', x)
16 return x
17
18
19def patch_greenlet(func):
20 """ Slove:
21 "Impossible to call blocking function in the event loop callback"
22
23 New problem:
24 this wrapper function is called after global gevent.joinall.
25 I can use gevent.pool.Pool() to spawn in this function and join globally.
26 But here I user [do_sth(t.value) for t in tasks] in the last of this program.
27
28 """
29 def inner(*args, **kwargs):
30 return gevent.spawn(func, *args, **kwargs)
31 return inner
32
33
34@patch_greenlet
35def callback(green):
36 """ add sleep here, make it blocking function.
37 error: "Impossible to call blocking function in the event loop callback"
38 """
39 time.sleep(3)
40 y = green.value
41 print('callback: ', y)
42
43def callback_v2(green):
44 time.sleep(3)
45 y = green.value
46 print('callback: ', y)
47
48def blocking_callback():
49 """ return:
50 time python gevent_callback_blocking.py
51 before join
52 add result: 5
53 callback: 5
54 add result: 4
55 after join
56 python gevent_callback_blocking.py 0.05s user 0.02s system 1% cpu 5.581 total
57 """
58 tasks = []
59 t1 = gevent.spawn_later(0, add_func, 3)
60 t1.rawlink(callback)
61 tasks.append(t1)
62
63 t2 = gevent.spawn_later(5, add_func, 2)
64 t2.rawlink(callback)
65 tasks.append(t2)
66
67
68 print('before join')
69 gevent.joinall(tasks)
70 print('after join')
71
72
73def blocking_callback_v2():
74 tasks = []
75 t1 = gevent.spawn_later(0, add_func, 3)
76 tasks.append(t1)
77
78 t2 = gevent.spawn_later(10, add_func, 2)
79 tasks.append(t2)
80
81
82 print('before join')
83 gevent.joinall(tasks)
84 print('after join')
85
86 for t in tasks:
87 callback_v2(t)
88
89blocking_callback_v2()