Setting up aiohttp.web applications#
There are many ways on setting up aiohttp.web
application, as well as there
are many ways of defining settings for them.
Most notable ways of managing settings are:
Importing Python settings module and store it within
aiohttp.web.Application
instanceReading settings from
.yaml
or.json
file and store it again, in application instance
With that in mind, rororo insists of their way for setting up
aiohttp.web
application.
Step 1. Settings data structure#
The main part of setup is Settings data structure backed by brilliant environ-config library. It stores all settings values, as well as any other settings related data.
Example below illustrates how given Settings data structure may look like,
import environ
@environ.config(prefix=None, frozen=True)
class Settings:
level: str
debug: bool
rororo provides basic data structure, which covers most of common settings,
used withing aiohttp.web
app. Given data structure available as:
rororo.settings.BaseSettings
and it contains next fields,
Attrib |
Env var |
Description |
---|---|---|
|
|
Host, where |
|
|
Port to run |
|
|
When enabled, means that |
|
|
Application level (can be used as |
|
|
Time zone to use within application. By default: |
|
|
First weekday for calendar and other modules. By default: |
|
|
Locale to use within app. By default: |
|
|
Sentry DSN to use. By default: |
|
|
Sentry release. By default: |
rororo elevates on 12factor configuration principles, which means all values for Settings data structure should come from environment.
Step 2. Instantiating settings#
After you declare your Settings data structure it is needed to:
Instantiate it
Assign to the
aiohttp.web.Application
instance
In most cases, it should looks like,
from aiohttp import web
from .settings import Settings
def create_app(
argv: List[str] = None, *, settings: Settings = None
) -> web.Application:
# Instantiate settings if needed
if settings is None:
settings = Settings().from_environ()
# Instantiate app
app = web.Application(...)
# Assign settings to the application for later reusage
app["settings"] = settings
# Return app
return app
You also, might want to “apply” settings by running,
settings.apply()
right after instantiation. In that case
rororo.settings.BaseSettings.apply()
will call,
functions with respected settings values.
Configuring Sentry SDK#
Even rororo.settings.BaseSettings
contains values to configure
Sentry, it is not designed to call sentry_sdk.init
on rororo.settings.BaseSettings.apply()
run.
You must need to setup Sentry SDK by yourself like,
import logging
import sentry_sdk
from sentry_sdk.integrations.aiohttp import AioHttpIntegration
from sentry_sdk.integrations.logging import LoggingIntegartion
def create_app(argv: List[str] = None) -> web.Application:
settings = Settings.from_environ()
if settings.sentry_dsn:
sentry_sdk.init(
settings.sentry_dsn,
environment=settings.level,
release=settings.sentry_release,
integrations=(
AioHttpIntegration(),
LoggingIntegration(event_level=logging.WARNING),
),
)
...
Setup shortcut#
There is a rororo.settings.setup_settings_from_environ()
&
rororo.settings.setup_settings()
shortcuts, which apply given Settings
data structure and put given instance into aiohttp.web.Application
dict as "settings"
key.
In other words given function is a literally shortcut to,
settings.apply(...)
app["settings"] = settings
Step 3. Using settings#
In app.__main__
script#
If you run your app
not via python -m aiohttp.web
, but via application
own __main__.py
, it is OK to,
Run
create_app
factory functionRead
settings
from resulted appPass
host
/port
and other values toaiohttp.web.run_app()
function
In most cases that __main__.py
will look like,
from aiohttp import web
from rororo.aio import ACCESS_LOG_FORMAT
from rororo.settings import APP_SETTINGS_KEY
from app.app import create_app, logger
from app.settings import Settings
if __name__ == "__main__":
app = create_app()
settings: Settings = app[APP_SETTINGS_KEY]
is_dev = settings.is_dev
if is_dev:
import aiohttp_autoreload
aiohttp_autoreload.start()
web.run_app(
host=settings.host,
port=settings.port,
access_log=logger if is_dev else None,
access_log_format=ACCESS_LOG_FORMAT,
)
Within view functions#
As aiohttp.web.Request
instance contains link to app
, which
requests given view handler, it is straight forward to read the settings within
the view as,
from aiohttp import web
from rororo.settings import APP_SETTINGS_KEY
async def index(request: web.Request) -> web.Response:
if request.app[APP_SETTINGS_KEY].debug:
print("Hello, world!")
return web.json_response(True)
However, as aiohttp>=3
supports sub-apps it is considred to more robust
using aiohttp.web.Request.config_dict
for accessing Settings data
structure,
if request.config_dict[APP_SETTINGS_KEY].debug:
print("Hello, world!")