[英]Python - Unable to use multiple event loops with aiohttp
I am trying to make a code similar to this one work. 我正在尝试编写类似于此工作的代码。
class FooFoo:
def __init__(self):
loop = asyncio.get_event_loop()
self.value = loop.run_until_complete(self.async_work())
async def async_work(self):
return 10
def build_server():
app = web.Application()
app.router.add_route('GET', '/', hello)
web.run_app(app, 'localhost', '12000')
async def hello(request):
foo = await FooFoo()
return web.json_response{'ip': request.remote, 'value': foo.value}
Doing a curl http://127.0.0.1:/
yields this error: curl http://127.0.0.1:/
产生此错误:
Error handling request
Traceback (most recent call last):
File "/usr/local/lib64/python3.6/site-packages/aiohttp/web_protocol.py", line 418, in start
resp = await task
File "/usr/local/lib64/python3.6/site-packages/aiohttp/web_app.py", line 458, in _handle
resp = await handler(request)
File "/usr/local/lib64/python3.6/site-packages/aiohttp/web_urldispatcher.py", line 155, in handler_wrapper
result = old_handler(request)
File "test.py", line 36, in hello
foo = asyncio.get_event_loop().run_until_complete(FooFoo())
File "test.py", line 24, in __init__
self.value = loop.run_until_complete(self.async_work())
File "/usr/lib64/python3.6/asyncio/base_events.py", line 471, in run_until_complete
self.run_forever()
File "/usr/lib64/python3.6/asyncio/base_events.py", line 425, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
This happens because the server is running on the event loop and FooFoo
is wants to rerun the loop. 发生这种情况是因为服务器在事件循环上运行,并且
FooFoo
要重新运行循环。
Solutions I've tried : 我尝试过的解决方案:
hello
function into a synchronous one with : foo = asyncio.get_event_loop().run_until_complete(FooFoo())
, gives the same error. hello
函数更改为同步函数: foo = asyncio.get_event_loop().run_until_complete(FooFoo())
, foo = asyncio.get_event_loop().run_until_complete(FooFoo())
产生相同的错误。 RuntimeError: Cannot run the event loop while another loop is running
I need to be able to run multiple loops, or if you have a better solution I'd take it. 我需要能够运行多个循环,或者如果您有更好的解决方案,我会接受。
If it helps I am using python 3.6.8 如果有帮助,我正在使用python 3.6.8
If you change the logic slightly to something like this: 如果您将逻辑略微更改为如下所示:
import asyncio
from aiohttp import web
class FooFoo(object):
async def async_work(self):
await asyncio.sleep(1)
self.value = 10
async def hello(request):
foo = FooFoo()
await foo.async_work()
return web.json_response({'ip': request.remote, 'value': foo.value})
def build_server():
app = web.Application()
app.router.add_route('GET', '/', hello)
web.run_app(app, host='localhost', port=8080)
you'll get it working. 您将使其正常运行。
UPDATE Given the details from the OP comments: 更新给出了OP注释的详细信息:
the FooFoo class is a client that generates a token via asynchronous requests to a server.
FooFoo类是一个客户端,它通过对服务器的异步请求生成令牌。 The user isn't supposed to instantiate FooFoo, then generate a token later.
用户不应该实例化FooFoo,然后再生成令牌。
I'd suggest using a builder pattern which is used to simplify creation of complex objects. 我建议使用一个构建器模式 ,该模式用于简化复杂对象的创建。 I think this pattern fits to this case just fine.
我认为这种模式适合这种情况。 In order to apply the pattern, we add a new
FooFooBuilder
class: 为了应用模式,我们添加了一个新的
FooFooBuilder
类:
async def request_token():
await asyncio.sleep(1)
return 42
class FooFooBuilder(object):
@staticmethod
async def build():
token = await request_token()
# Do token validation and error handling.
return FooFoo(token)
The FooFoo
class will take the token
as its argument during instantiation: FooFoo
类在实例化期间将token
作为其参数:
class FooFoo(object):
def __init__(self, token):
self.value = token
So that the hello
request handler will change to: 这样,
hello
请求处理程序将更改为:
async def hello(request):
foo = await FooFooBuilder.build()
return web.json_response({'ip': request.remote, 'value': foo.value})
With this approach, there is no need to use multiple event loops to get things done. 使用这种方法,无需使用多个事件循环即可完成工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.