Niet that I do not neccesarily expect that the example would keep working as dependencies change. However, perhaps there鈥檚 an easy fix or insightful remark that鈥檒l help me :)
Issue
The example ASGI server does not work with Uvicorn 0.6, but it does work with Uvicorn 0.3.
if __name__ == '__main__':
loop = auto_loop_setup()
sio.start_background_task(background_task)
uvicorn.run(app, '127.0.0.1', 5000, loop=loop)
Error
[...]site-packages/uvicorn/protocols/http/httptools_impl.py:20: RuntimeWarning: coroutine 'render' was never awaited
status_code: _get_status_line(status_code) for status_code in range(100, 600)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
2019-03-28 16:21:14,464 ERROR Task was destroyed but it is pending!
What I think
It seems you no longer pass the loop to uvicorn. If you check for the current loop after 'auto_loop_setup()' then there is a loop, but it hasn't started yet.
Why I'm interested
I have a hardware project where a single thread can change some GPIO pins. Preferably I keep everything in asyncio: in that way I get parallelism, socket connections with a global state (GPIO pins) without locking/.
It's unfortunate that uvicorn changed in a way that broke these examples, but I'll see if I can fix everything to work again. Thanks.
I got python-socketio working together with background tasks on uvicorn. Additionally I made it work together with Starlette. I didn't see an example here, so perhaps it's a nice example to add.
import logging
import asyncio
import uvicorn
from uvicorn.loops.uvloop import uvloop_setup
from starlette.applications import Starlette
from starlette.responses import JSONResponse
import socketio
# Set some basic logging
logging.basicConfig(
level=2,
format="%(asctime)-15s %(levelname)-8s %(message)s"
)
# Create a basic app
sio = socketio.AsyncServer(async_mode='asgi')
star_app = Starlette(debug=True)
app = socketio.ASGIApp(sio, star_app)
@star_app.route('/')
async def homepage(request):
return JSONResponse({'hello': 'world'})
@sio.on('connect')
async def connect(sid, environ):
logging.info(f"connect {sid}")
@sio.on('message')
async def message(sid, data):
logging.info(f"message {data}")
# await device.set(data)
@sio.on('disconnect')
async def disconnect(sid):
logging.info(f'disconnect {sid}')
# Set up the event loop
async def start_background_tasks():
while True:
logging.info(f"Background tasks that ticks every 10s.")
await sio.sleep(10.0)
async def start_uvicorn():
uvicorn.run(app, host='0.0.0.0', port=8000)
async def main(loop):
bg_task = loop.create_task(start_background_tasks())
uv_task = loop.create_task(start_uvicorn())
await asyncio.wait([bg_task, uv_task])
if __name__ == '__main__':
uvloop_setup()
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()
Probably you can also add background tasks from the event handlers. That also worked in the original example, so that should still work.
If you want I can make a pull request with a sample (similar to the other samples). However, the background_task would have a slightly different API (as in: I use the asyncio way to schedule functions and not the function in python-socketio-library.
I have addressed the problems with uvicorn now.
Most helpful comment
I got
python-socketioworking together with background tasks onuvicorn. Additionally I made it work together with Starlette. I didn't see an example here, so perhaps it's a nice example to add.Probably you can also add background tasks from the event handlers. That also worked in the original example, so that should still work.
If you want I can make a pull request with a sample (similar to the other samples). However, the background_task would have a slightly different API (as in: I use the asyncio way to schedule functions and not the function in python-socketio-library.