devtools can not work with session[aioredis]
ipfans opened this issue · comments
- aiohttp-devtools version:
0.6.4 - aiohttp version:
2.3.4 - python version:
3.6.3 - Platform:
OSX
Issue Summary
Starting with adev runserver simple.py
will raise RuntimeError: This event loop is already running
but it works for python simple.py
Code Example
#simple.py
from aiohttp import web
import asyncio
import aioredis
from aiohttp_session import setup, get_session
from aiohttp_session.redis_storage import RedisStorage
async def create_redis_pool():
return await aioredis.create_pool(('127.0.0.1', 6379))
def setup_sessions(app, pool):
storage = RedisStorage(pool)
setup(app, storage)
async def index(request):
sess = await get_session(request)
last_visit = sess['last_visit'] if 'last_visit' in sess else "never"
sess['last_visit'] = "yes"
return web.Response(text=last_visit)
def create_app():
loop = asyncio.get_event_loop()
pool = loop.run_until_complete(create_redis_pool())
app = web.Application()
setup_sessions(app, pool)
app.router.add_get("/", index)
return app
if __name__ == '__main__':
web.run_app(create_app(), port=8000)
Steps to reproduce
adev runserver simple.py
.- check out error message.
This is not an error, this is you not using aiohttp correctly.
Look at onstartup.
I already tried signal on aiohttp before I opened this issue, but it raised another error. This code snippet is from demo of aiohttp-session, and it should be works. Of course, both versions are working fine on python simple.py
command. So I think it caused by adev command.
e.x.
# simple.py
from aiohttp import web
import asyncio
import aioredis
from aiohttp_session import setup, get_session
from aiohttp_session.redis_storage import RedisStorage
async def create_redis_pool():
return await aioredis.create_pool(('127.0.0.1', 6379))
async def setup_sessions(app):
pool = await create_redis_pool()
storage = RedisStorage(pool)
setup(app, storage)
async def index(request):
sess = await get_session(request)
last_visit = sess['last_visit'] if 'last_visit' in sess else "never"
sess['last_visit'] = "yes"
return web.Response(text=last_visit)
def create_app():
app = web.Application()
app.on_startup.append(setup_sessions)
app.router.add_get("/", index)
return app
if __name__ == '__main__':
web.run_app(create_app(), port=8000)
traceback:
$ adev runserver simple.py
[21:13:29] pre-check enabled, checking app factory
[21:13:29] Starting aux server at http://localhost:8001 ◆
[21:13:29] Starting dev server at http://localhost:8000 ●
Process Process-1:
Traceback (most recent call last):
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp_devtools/runserver/serve.py", line 124, in serve_main_app
loop.run_until_complete(app.startup())
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
return future.result()
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/web.py", line 264, in startup
yield from self.on_startup.send(self)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/signals.py", line 51, in send
yield from self._send(*args, **kwargs)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/signals.py", line 17, in _send
yield from res
File "/Users/user/Developer/projects/new/simple.py", line 16, in setup_sessions
setup(app, storage)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp_session/__init__.py", line 158, in setup
app.middlewares.append(session_middleware(storage))
AttributeError: 'tuple' object has no attribute 'append'
Humm, for me this is a result of the dumb way aiohttp-sessions is setup.
I'll try to make a pull request there to fix how it works. In the meantime you can avoid this issue with --no-pre-check
, eg. run adev runserver --no-pre-check session_demo.py
.
Sorry to be curt early, main of the issues here are just simple questions about usage.
@samuelcolvin I also tried disable pre-check at first time, but it also not work for me.
$ adev runserver --no-pre-check simple.py
[21:40:34] Starting aux server at http://localhost:8001 ◆
[21:40:34] Starting dev server at http://localhost:8000 ●
Process Process-1:
Traceback (most recent call last):
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp_devtools/runserver/serve.py", line 124, in serve_main_app
loop.run_until_complete(app.startup())
File "/Users/user/.pyenv/versions/3.6.3/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
return future.result()
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/web.py", line 264, in startup
yield from self.on_startup.send(self)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/signals.py", line 51, in send
yield from self._send(*args, **kwargs)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp/signals.py", line 17, in _send
yield from res
File "/Users/user/Developer/projects/new/simple.py", line 16, in setup_sessions
setup(app, storage)
File "/Users/user/.local/share/virtualenvs/new-y2QdrW3f/lib/python3.6/site-packages/aiohttp_session/__init__.py", line 158, in setup
app.middlewares.append(session_middleware(storage))
AttributeError: 'tuple' object has no attribute 'append'
Use the first snippet, not the second.
If you look in setup
it just adds middleware which you can't do once the app is frozen, so you can't call it in a startup coroutine.
@samuelcolvin My first snippet is a problem that adev runs a ioloop, I can not use run_until_complete
to call async func. But I also can not find another way to init aioreids pool before app is frozen. Maybe I am not found a right way to use a blocking coroutine call, because callback often called after app frozen.
I think it maybe two ways to fix this:
- When call
create_app
, adev should stop asyncio loop.(It seems that will be a big project.) - Support
create_app
func to be a coroutine. (I am trying this.)
(env) aiohttp-devtools 0 174ms ➤ echo "THIS IS COPIED VERBATIM FROM THE FIRST SNIPPET IN YOUR ISSUE!"
THIS IS COPIED VERBATIM FROM THE FIRST SNIPPET IN YOUR ISSUE!
(env) aiohttp-devtools 0 164ms ➤ cat session_demo.py
from aiohttp import web
import asyncio
import aioredis
from aiohttp_session import setup, get_session
from aiohttp_session.redis_storage import RedisStorage
async def create_redis_pool():
return await aioredis.create_pool(('127.0.0.1', 6379))
def setup_sessions(app, pool):
storage = RedisStorage(pool)
setup(app, storage)
async def index(request):
sess = await get_session(request)
last_visit = sess['last_visit'] if 'last_visit' in sess else "never"
sess['last_visit'] = "yes"
return web.Response(text=last_visit)
def create_app():
loop = asyncio.get_event_loop()
pool = loop.run_until_complete(create_redis_pool())
app = web.Application()
setup_sessions(app, pool)
app.router.add_get("/", index)
return app
if __name__ == '__main__':
web.run_app(create_app(), port=8000)
(env) aiohttp-devtools 0 2.04s ➤ adev runserver --no-pre-check session_demo.py
[13:54:12] Starting aux server at http://localhost:8001 ◆
[13:54:12] Starting dev server at http://localhost:8000 ●
[13:54:14] ● GET / 200 233B
[13:54:14] ● GET / 200 233B
[13:54:14] ● GET / 200 233B
^C[13:54:16] shutting down server...
(env) aiohttp-devtools 0 5.24s ➤
Is your behaviour different to this?
@samuelcolvin I checked my history, it seems that disable pre-check is OK. Sorry about that.