mirai
is a port of Twitter Futures to python powered by a backport of
Python 3.2's concurrent.futures. mirai
offers a simpler
operator chaining-based way for using promises and futures.
mirai
is available on pypi. Installation
is as simple as using pip
,
$ pip install mirai --upgrade
mirai
is based around the concept of a Promises -- containers that
are populated with the result of an asynchronous computation. Promises provide
a more streamlined way for dealing with asynchronous code than callbacks.
from mirai import Promise
import funcy as fu
(
Promise
# `call` is a way to execute a synchronous function asynchronously. It
# returns a Promise you can use to queue up callbacks
.call(twitter.get_followers, "duck")
# `map` means "create another Promise by applying the following function to
# my contents." If the previous Promise threw an exception, this callback
# won't execute, and the resulting Promise will contain the previous
# Promise's exception.
.map(lambda followers: [
Future.call(twitter.get_latest_posts, follow)
for follower in followers
])
# `Promise.collect` turns a sequence of promises into a Promise with a
# sequence of items. If you have many sources for Promises, you can use
# `Promise.collect` to bundle them together. Notice that we're using
# `Promise.flatmap` here -- that's because `Promise.collect` returns a
# Promise, not a normal value. If we didn't use flatmap, we'd end up with a
# Promise containing another Promise!
.flatmap(Promise.collect)
# Each follower gave me a list of tweets, so rather than dealing a list of
# lists, lets just turn it into a flat list of tweets
.map(fu.flatten)
# `Promise.onsuccess` and `Promise.onfailure` allow you to attach a callback
# that doesn't actually affect the Promise's value. Great for logging!
.onsuccess(lambda tweets: print("Retrieved {:,d} Tweets from my followers"))
# Notice how we turned what could have been a synchronous double-for loop
# into a series of asynchronous calls? Pretty awesome!
.map(lambda tweets: [
Future.call(twitter.retweet, tweet)
for tweet in tweets
])
.flatmap(Future.collect)
.onsuccess(lambda retweets: print("I love EVERYBODY!"))
# You can use `Promise.rescue` to turn a failing Promise into a successfuly
# one, too.
.rescue(lambda e: Future.value("Something went wrong...oh well"))
# All of the above isn't executed until you request it's data, so don't
# forget to call `Promise.get`! You can also use `Promise.join` and
# `Promise.select` if you want to gather many Promises or just want the first
# that finishes.
.get()
)
Learn more about mirai
at http://mirai.readthedocs.org/