Henson¶
Henson is a library for building services that are driven by consumers. Henson applications read from objects that implement the Consumer Interface and provide the message received to a callback for processing. The messsage can be processed before handing it off to the callback, and the callback’s results can be processed after they are returned to the application.
Note
This documentation uses the async
/await
syntax introduced to Python
3.5 by way of PEP 492. If you
are using an older version of Python, replace async
with the
@asyncio.coroutine
decorator and await
with yield from
.
Installation¶
You can install Henson using Pip:
$ python -m pip install henson
You can also install it from source:
$ python setup.py install
Quickstart¶
from henson import Abort, Application
class FileConsumer:
"""Read lines from a file."""
def __init__(self, filename):
self.filename = filename
self._file = None
def __iter__(self):
"""FileConsumer objects are iterators."""
return self
def __next__(self):
"""Return the next line of the file, if available."""
if not self._file:
self._file = open(self.filename)
try:
return next(self._file)
except StopIteration:
self._file.close()
raise Abort('Reached end of file', None)
async def read(self):
"""Return the next line in the file."""
return next(self)
async def callback(app, message):
"""Print the message retrieved from the file consumer."""
print(app.name, 'received:', message)
return message
app = Application(
__name__,
callback=callback,
consumer=FileConsumer(__file__),
)
@app.startup
async def print_header(app):
"""Print a header for the file being processed."""
print('# Begin processing', app.consumer.filename)
@app.teardown
async def print_footer(app):
"""Print a footer for the file being processed."""
print('# Done processing', app.consumer.filename)
@app.message_preprocessor
async def remove_comments(app, line):
"""Abort processing of comments (lines that start with #)."""
if line.strip().startswith('#'):
raise Abort('Line is a comment', line)
return line
Running Applications¶
Henson provides a henson
command to run your applications from the command
line. To run the application defined in the quickstart above, cd
to the
directory containing the module and run:
$ henson run file_printer
Henson’s CLI can also be invoked by running the installed package as a script. To avoid confusion and prevent different installations of Henson from interfering with one another, this is the recommended way to run Henson applications:
$ python -m henson run file_printer
If a module contains only one instance of a Henson
Application
, python -m henson run
will automatically
detect and run it. If more than one instance exists, the desired application’s
name must be specified:
$ python -m henson run file_printer:app
This form always takes precedence over the former, and the henson
command
won’t attempt to auto-detect an instance even if there is a problem with the
name specified. If the attribute specified by the name after :
is callable,
python -m henson run
will call it and use the returned value as the
application. Any callable specified this way should require no arguments and
return an instance of Application
. Autodiscovery of
callables that return applications is not currently supported.
More detailed information about Henson’s command line interface can be found in Command Line Interface.
Logging¶
Henson applications provide a default logger. The logger returned by calling
logging.getLogger()
will be used. The name of the logger is the name
given to the application. Any configuration needed (e.g.,
logging.basicConfig()
, logging.config.dictConfig()
, etc.) should be
done before the application is started.
Debug Mode¶
Debugging with asyncio can be tricky. Henson provides a debug mode enables asyncio’s debug mode as well as debugging information through Henson’s logger.
Debug mode can be enabled through a configuration setting:
app.settings['DEBUG'] = True
or by providing a truthy value for debug
when calling
run_forever()
:
app.run_forever(debug=True)
Contents: