DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

Put on Your Monocle and Do Some Async Programming

Mitch Pronschinske user avatar by
Mitch Pronschinske
·
Jul. 28, 10 · Interview
Like (0)
Save
Tweet
Share
7.60K Views

Join the DZone community and get the full member experience.

Join For Free
Greg and Steven Hazel from Sauce Labs have recently built what they call, "An async programming framework with a blocking look-alike syntax".  This framework, named Monocle, is focused on being portable between event-driven I/O frameworks.  Currently, Monocle supports the Twisted and Tornado frameworks.

For those who haven't heard of Sauce Labs, they were co-founded by John Huggins, the creator of Selenium.  Sauce Labs' free and commercial tools build on top of the core Selenium testing framework.

The emergence of Monocle could indicate that Sauce Labs is taking a more focused look at event-driven code and its role in concurrent web performance.  Event-driven code is efficient and intuitive, but sometimes procedures are are split up and code is expanded in a not-so-good way.  

Anytime you do I/O, you have to register a new handler and then return to the event loop so that you can let other things happen while the I/O finishes.  Hazel and Hazel said, "It would be nice if we had some way to tell the event loop to call back into the middle of our function, so we could just continue where we left off."  In Python, they found a mechanism that can do just that.  

The mechanisms are called generators, and Monocle uses this Python syntax supported by Python 2.5 and up.  The generators in Monocle straighten out event-based code such as this blocking code (expanded into four functions):
def get_cmd(conn):
conn.read_until("\n", callback=handle_cmd)

def handle_cmd(conn, cmd):
if cmd.type == "get-address":
# keep track of the conn so we can write the response back!
def callback(result):
handle_user_query_result(conn, result)
db.query(cmd.username, callback)
else:
conn.write("unknown command")

def handle_user_query_result(conn, user):
conn.write(user.address)
Which is transformed into code like this, via Monocle:
@_o
def do_cmd(conn):
cmd = yield conn.read_until("\n")
if cmd.type == "get-address":
user = yield db.query(cmd.username)
yield conn.write(user.address)
else:
yield conn.write("unknown command")
Sauce Labs believes Monocle will make code easier to work with than multi-threaded code, thanks to its "cooperative concurrency" approach.

Here's a basic Monocle program running two concurrent processes called "o-routines" using Tornado's event loop.  One process is an HTTP server, and the other makes an HTTP request:
import monocle
monocle.init("tornado")

from monocle.stack import eventloop
from monocle.stack.network import add_service
from monocle.stack.network.http import HttpClient, HttpHeaders, HttpServer, http_respond

@monocle.o
def hello_http(req):
content = "Hello, World!"
headers = HttpHeaders()
headers['Content-Length'] = len(content)
headers['Content-Type'] = 'text/plain'
yield http_respond(req, 200, headers, content)

@monocle.o
def request():
client = HttpClient()
resp = yield client.request('http://127.0.0.1:8088/')
print resp.code, resp.body

add_service(HttpServer(hello_http, 8088))
monocle.launch(request())
eventloop.run()
And instead of @monocle.o, you can use the don the monocle (@_o) as a shortcut:
from monocle import _o

@_o
def request():
client = HttpClient()
resp = yield client.request('http://127.0.0.1:8088/')
print resp.code, resp.body
Hazel and Hazel admit, "this violates Python's convention that underscores indicate variables for internal use. But rules are for breaking. Live a little."

Check out Monocle on GitHub.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Choosing the Right Framework for Your Project
  • DevOps for Developers — Introduction and Version Control
  • 10 Most Popular Frameworks for Building RESTful APIs
  • Software Maintenance Models

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: