monocle
所属分类:前端开发
开发工具:Python
文件大小:57KB
下载次数:0
上传日期:2020-09-03 13:46:18
上 传 者:
sh-1993
说明: 一个异步编程框架,具有类似块的语法。
(An async programming framework with a blocking look-alike syntax.)
文件列表:
.landscape.yml (78, 2020-09-03)
.travis.yml (715, 2020-09-03)
CONTRIBUTING.md (3650, 2020-09-03)
LICENSE (1685, 2020-09-03)
examples (0, 2020-09-03)
examples\basics.py (889, 2020-09-03)
examples\client_server.py (988, 2020-09-03)
examples\client_timeouts.py (609, 2020-09-03)
examples\echo_server.py (349, 2020-09-03)
examples\eventloop.py (545, 2020-09-03)
examples\http_client.py (819, 2020-09-03)
examples\http_server.py (651, 2020-09-03)
examples\https.py (497, 2020-09-03)
examples\repl_debugging.py (349, 2020-09-03)
examples\service_error.py (342, 2020-09-03)
examples\sieve.py (3881, 2020-09-03)
examples\simplechan.py (459, 2020-09-03)
examples\sleep.py (502, 2020-09-03)
examples\tb.py (589, 2020-09-03)
examples\tcp_proxy.py (655, 2020-09-03)
examples\webserver.py (792, 2020-09-03)
monocle (0, 2020-09-03)
monocle\__init__.py (282, 2020-09-03)
monocle\asyncore_stack (0, 2020-09-03)
monocle\asyncore_stack\__init__.py (0, 2020-09-03)
monocle\asyncore_stack\eventloop.py (1075, 2020-09-03)
monocle\asyncore_stack\network (0, 2020-09-03)
monocle\asyncore_stack\network\__init__.py (3404, 2020-09-03)
monocle\callback.py (768, 2020-09-03)
monocle\core.py (10004, 2020-09-03)
monocle\experimental.py (2264, 2020-09-03)
monocle\monocle_mock.py (1932, 2020-09-03)
monocle\repl.py (4244, 2020-09-03)
monocle\script_util.py (442, 2020-09-03)
monocle\stack (0, 2020-09-03)
monocle\stack\__init__.py (455, 2020-09-03)
monocle\stack\eventloop.py (485, 2020-09-03)
... ...
# monocle
## An async programming framework with a blocking look-alike syntax.
[![pypi](https://img.shields.io/pypi/v/monocle.svg)](https://pypi.python.org/pypi/monocle/)
[![Build Status](https://travis-ci.org/saucelabs/monocle.png?branch=master)](https://travis-ci.org/saucelabs/monocle)
> !! Monocle only supports Python v2 which has reached end of life (EOL)
on January 1st, 2020. We don't recommend to use this package anymore. !!
Monocle straightens out event-driven code using Python's generators.
It aims to be portable between event-driven I/O frameworks, and
currently supports Twisted and Tornado.
It's for Python 2.7 only; the syntax it uses isn't supported in older
versions of Python. Monocle has not yet been updated for Python 3.
## A Simple Example
Here's a simple monocle program that runs two concurrent lightweight
processes (called "o-routines") using Tornado's event loop. One is an
HTTP server, and the other makes an HTTP request:
```python
import monocle
monocle.init("tornado")
from monocle import Return
from monocle.stack import eventloop
from monocle.stack.network import add_service
from monocle.stack.network.http import HttpClient, HttpHeaders, HttpServer
@monocle.o
def hello_http(req):
content = "Hello, World!"
headers = HttpHeaders()
headers['Content-Length'] = len(content)
headers['Content-Type'] = 'text/plain'
yield Return(200, headers, content)
@monocle.o
def request():
resp = yield HttpClient.query('http://127.0.0.1:8088/')
print resp.code, resp.body
add_service(HttpServer(8088, hello_http))
monocle.launch(request)
eventloop.run()
```
## @_o
It's important that code be dapper and well-dressed, so if you prefer,
you can don the monocle and use this handy shortcut for `@monocle.o`:
```python
from monocle import _o
@_o
def request():
client = HttpClient()
resp = yield client.request('http://127.0.0.1:8088/')
print resp.code, resp.body
```
It's true, this violates Python's convention that underscores indicate
variables for internal use. But rules are for breaking. Live a
little.
## The Big Idea
Event-driven code can be efficient and easy to reason about, but it
often splits up procedures in an unpleasant way. Here's an example of
a blocking function to read a request from a user, query a database,
and return a result:
```python
def do_cmd(conn):
cmd = conn.read_until("\n")
if cmd.type == "get-address":
user = db.query(cmd.username)
conn.write(user.address)
else:
conn.write("unknown command")
```
Here's the same thing in event-driven style, using callbacks:
```python
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)
```
What started out as a single function in the blocking code has
expanded here into four functions (counting the `callback` closure
that captures `conn` in `handle_cmd`). In real event-driven code,
this kind of thing happens a *lot*. Any time we want to do I/O, we
have to register a new handler and return back out to the event loop
to let other things happen while we wait for the I/O to finish. 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.
Fortunately, Python has a mechanism that lets us do exactly that,
called generators. Monocle uses generators to straighten out
event-driven code.
Here's the monocle equivalent of the event-based code above:
```python
@_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")
```
It's event-driven for efficient concurrency, but otherwise looks a lot
like the original blocking code. Each time you see the word `yield`
in the code above, the o-routine is returning back up to the event
loop and waiting to be called back when the I/O it requested
completes.
This approach is a kind of cooperative concurrency that makes for
simpler code than callback-based event-driven code, but which we think
is easier to reason about than multi-threaded code.
## A word about the word `yield`
In ordinary Python generators, the norm is to think of `yield` as in
*crops*: the generator yields a value. In monocle o-routines, it's
helpful to think of `yield` as in *traffic*. `yield conn.read(10)` in
an o-routine means "yield to other o-routines until we finish reading
10 bytes".
## Developer information
To run individual tests on your computer install py.test and the packages for
the backend you’d like to test. Here’s how to do it in a separate virtualenv
with Twisted:
$ cd monocle/
$ virtualenv --clear --no-site-package .venv
$ .venv/bin/pip install pytest twisted
...
You run the tests like this:
$ .venv/bin/python o_test.py twisted tests/
Alternatively you can use tox to run all the tests for the different backends:
$ .venv/bin/pip install tox
...
$ tox
Check tox.ini to see how the tests are run.
## Who?
Monocle was created by Greg Hazel and Steven Hazel.
## Related Work
monocle is similar to, and takes inspiration from:
* Twisted's inlineCallbacks
* BitTorrent's yielddefer (used in the 5.x mainline client)
* diesel
* Go's goroutines (and CSP generally)
* Haskell's I/O monad
* eventlet
近期下载者:
相关文件:
收藏者: