Last active
September 28, 2016 13:56
-
-
Save jomido/8ff072d5d1406f3c277dc78654457f9b to your computer and use it in GitHub Desktop.
Twisted Sync & Async (@in_thread & @in_reactor)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import random | |
| import time | |
| from twisted.internet import task | |
| from twisted.internet.defer import ( | |
| inlineCallbacks as inline, | |
| returnValue, | |
| DeferredList as when_all | |
| ) | |
| from utils import in_thread, in_reactor, sleep, repeating | |
| @in_thread | |
| def cpu_burner(t): | |
| print ("cpu burner ({}) starts burning".format(t)) | |
| time.sleep(t) | |
| result = random.randint(1, 10) | |
| print ('cpu burner ({}) is done burning, result = {}'.format(t, result)) | |
| print ('cpu burner ({}) is calling the network'.format(t)) | |
| n = some_network_call(result) | |
| print ("cpu burner ({}) is done the network call".format(t)) | |
| return n | |
| @in_reactor | |
| @inline | |
| def some_network_call(x): | |
| yield sleep(1.5) | |
| result = x * 2 | |
| returnValue(result) | |
| @repeating(1.0) | |
| def tick(): | |
| print("tick") | |
| @inline | |
| def main(reactor): | |
| tick() | |
| # SEQUENTIAL CALLS | |
| result = yield cpu_burner(5) | |
| print("result: {}".format(result)) | |
| result = yield cpu_burner(4) | |
| print("result: {}".format(result)) | |
| # CONCURRENT CALLS | |
| results = yield when_all([cpu_burner(t) for t in [3, 7, 9]]) | |
| for result in results: | |
| success, payload = result | |
| print ('{}: {}'.format(success, payload)) | |
| if __name__ == "__main__": | |
| task.react(main) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| tick | |
| cpu burner (5) starts burning | |
| tick | |
| tick | |
| tick | |
| tick | |
| tick | |
| tick | |
| cpu burner (5) is done burning, result = 9 | |
| cpu burner (5) is calling the network | |
| tick | |
| tick | |
| cpu burner (5) is done the network call | |
| result: 18 | |
| cpu burner (4) starts burning | |
| tick | |
| tick | |
| tick | |
| tick | |
| tick | |
| cpu burner (4) is done burning, result = 9 | |
| cpu burner (4) is calling the network | |
| tick | |
| tick | |
| cpu burner (4) is done the network call | |
| result: 18 | |
| cpu burner (3) starts burning | |
| cpu burner (7) starts burning | |
| cpu burner (9) starts burning | |
| tick | |
| tick | |
| tick | |
| tick | |
| cpu burner (3) is done burning, result = 8 | |
| cpu burner (3) is calling the network | |
| tick | |
| tick | |
| cpu burner (3) is done the network call | |
| tick | |
| tick | |
| tick | |
| tick | |
| cpu burner (7) is done burning, result = 6 | |
| cpu burner (7) is calling the network | |
| tick | |
| tick | |
| cpu burner (7) is done the network call | |
| cpu burner (9) is done burning, result = 9 | |
| cpu burner (9) is calling the network | |
| tick | |
| tick | |
| cpu burner (9) is done the network call | |
| True: 16 | |
| True: 12 | |
| True: 18 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from functools import wraps | |
| from twisted.internet import reactor, threads | |
| from twisted.internet import defer | |
| def in_reactor(fn): | |
| """ | |
| Decorate a function to make it always run in the main reactor loop. | |
| """ | |
| @wraps(fn) | |
| def wrapper(*args, **kwargs): | |
| return threads.blockingCallFromThread(reactor, fn, *args, **kwargs) | |
| return wrapper | |
| def in_thread(fn): | |
| """ | |
| Decorate a function to make it always run in a thread. | |
| """ | |
| @wraps(fn) | |
| def wrapper(*args, **kwargs): | |
| return threads.deferToThread(fn, *args, **kwargs) | |
| return wrapper | |
| def sleep(secs): | |
| """ | |
| sleep for :secs seconds | |
| """ | |
| d = defer.Deferred() | |
| reactor.callLater(secs, d.callback, None) | |
| return d | |
| def repeating(period): | |
| """ | |
| Decorate a function/method to make it repeat every :period. If the callable | |
| returns False, cancel the repetition. | |
| NOTE: you still have to do an initial call on the function/method to kick | |
| it off | |
| """ | |
| def wrapper(fn): | |
| @wraps(fn) | |
| def wrapper(*args, **kwargs): | |
| if fn(*args, **kwargs) is not False: | |
| reactor.callLater(period, wrapper, *args, **kwargs) | |
| return wrapper | |
| return wrapper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment