My last to date Python project
eventlet
/ gevent
import asyncio
asyncio
import asyncio
async def hello_world() -> None:
print('Hello, world!')
asyncio.run(hello.world())
asyncio
is just an infrasctructureasyncio
itself is not suitable for web development
aiohttp.web
aiopg, asyncpg, aioredis, aio*
aiohttp.client
asyncio
stack providesasync
/ await
all around your code
aiohttp
from aiohttp import web
aiohttp.web
is not a rocket sciencefrom aiohttp import web
async def hello_world(request: web.Request) -> web.Response:
return web.json_response({'data': 'Hello, world!'})
app = web.Application()
app.router.add_get('/', hello_world)
web.run_app(app)
yourapp/__main__.py
import asyncio
import sys
import uvloop
from aiohttp import web
from yourapp.app import create_app
if __name__ == '__main__':
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
app = create_app()
sys.exit(web.run_app(app))
$ python -m yourapp
from aiopg.sa import create_engine
async def connect_db(app: web.Application) -> None:
app['db'] = await create_engine(app['config']['db']['url'])
async def disconnect_db(app: web.Application) -> None:
db = app.get('db')
if db:
db.close()
await db.wait_closed()
app.on_startup.append(connect_db)
app.on_shutdown.append(disconnect_db)
This is not a production-ready code!
async def upload_document(request: web.Request) -> web.Response:
data = await request.post()
files = {}
for file in data.values():
files[file.filename] = file.body
await upload_to_s3(file.filename, file.body)
async with request.app['db'].acquire() as conn:
for file in files:
await insert_document(conn, file)
return web.json_response(status=201)
And you might don't need it
query = (
sa.select([sa.func.max(document_file_table.c.content_length)])
.select_from(
select_from
.outerjoin(
document_file_table,
document_file_table.c.document_id == document_table.c.id,
)
.outerjoin(
document_meta_table,
document_meta_table.c.id == document_file_table.c.meta_id,
),
)
.where(sa.and_(
clause,
document_meta_table.c.is_current.is_(True),
document_file_table.c.type == DocumentFileType.original,
))
)
*.yaml
dict
you might want to start using
namedtuple
or dataclass
, or at least
StructedDict
await
statementawait
– asyncio is not your choiceasync def gzip_buffer(buffer: io.BytesIO,
*,
loop: asyncio.AbstractEventLoop) -> io.BytesIO:
"""Non-blocking way of compressing prepared bytes IO with gzip."""
return await loop.run_in_executor(None, sync_gzip_buffer, buffer)
aiohttp.web
sill in semi-active development@route
decorator)
aio-*
libs might not cover your caseweb.Application
is a context holderdict
app
instance everywhereaiohttp
is not a rocket scienceimport cProfile
profiler = cProfile.Profile()
if __name__ == '__main__':
use_profiler = os.environ.get('USE_PROFILER') == '1'
if use_profiler:
profiler.enable()
app = create_app()
try:
sys.exit(web.run_app(app))
finally:
if use_profiler:
profiler.dump_stats('yourapp.prof')
profiler.disable()
asyncio.run
contextvars
support