Python 需要一个中心代理来异步发送web请求,但如何将任务添加到其事件循环中
我希望实现一个代理类,该类由应用程序的其余部分用来异步发送web请求。我需要这个类,这样我就可以有一个中心点来控制流量,例如限制发送web请求的速度Python 需要一个中心代理来异步发送web请求,但如何将任务添加到其事件循环中,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,我希望实现一个代理类,该类由应用程序的其余部分用来异步发送web请求。我需要这个类,这样我就可以有一个中心点来控制流量,例如限制发送web请求的速度 import asyncio from time import sleep import threading from concurrent.futures import ThreadPoolExecutor class Proxy(): def __init__(self): self.loop = asyncio.g
import asyncio
from time import sleep
import threading
from concurrent.futures import ThreadPoolExecutor
class Proxy():
def __init__(self):
self.loop = asyncio.get_event_loop()
self.p = ThreadPoolExecutor(max_workers=3)
t = threading.Thread(target=self.start_event_loop, args=(self.loop,))
t.start()
def start_event_loop(self, loop):
asyncio.set_event_loop(loop)
print('running loop')
loop.run_forever()
def from_remote_server(self):
return 'hello'
@asyncio.coroutine
def get_async(self):
print('calling server...')
result = yield from self.loop.run_in_executor(self.p, self.from_remote_server)
print('result returned')
return result
proxy = Proxy()
for i in range(3):
asyncio.async(proxy.get_async())
for i in range(3):
asyncio.async(proxy.get_async())
这是我到目前为止的看法。。当Proxyclass初始化时,它会创建一个运行事件循环的后台线程,我这样做是因为在主线程中运行事件循环会阻止它之后的所有内容
get\u async用于将来自\u远程\u服务器的同步方法包装到asyncio协同路由中,这里使用的是loop.run\u in\u executor,通过使用ThreadPoolExecutor,我可以有效地限制触发web请求的速率
import asyncio
from time import sleep
import threading
from concurrent.futures import ThreadPoolExecutor
class Proxy():
def __init__(self):
self.loop = asyncio.get_event_loop()
self.p = ThreadPoolExecutor(max_workers=3)
t = threading.Thread(target=self.start_event_loop, args=(self.loop,))
t.start()
def start_event_loop(self, loop):
asyncio.set_event_loop(loop)
print('running loop')
loop.run_forever()
def from_remote_server(self):
return 'hello'
@asyncio.coroutine
def get_async(self):
print('calling server...')
result = yield from self.loop.run_in_executor(self.p, self.from_remote_server)
print('result returned')
return result
proxy = Proxy()
for i in range(3):
asyncio.async(proxy.get_async())
for i in range(3):
asyncio.async(proxy.get_async())
当客户端需要发送web请求时,它会使用asyncio.asyncproxy.get_async在事件循环中调度请求,这将返回一个任务,稍后可用于检索结果
这段代码实际上是有效的…结果如下:
running loop
calling server...
calling server...
calling server...
calling server...
calling server...
calling server...
result returned
result returned
result returned
result returned
result returned
result returned
然后我注意到一个问题,如果我在最后的两个for循环之间放置一个linesleep5:
for i in range(3):
asyncio.async(proxy.get_async())
sleep(5)
for i in range(3):
asyncio.async(proxy.get_async())
然后输出仅显示3个正在调用的服务器。。。就好像第二个循环没有向事件循环添加新任务一样
running loop
calling server...
calling server...
calling server...
result returned
result returned
result returned
这几乎就像我必须立即调用asyncio.asyncproxy.get\u async,它才能工作
我检查了循环和线程的状态,它们看起来很好
print(proxy.loop)
<_WindowsSelectorEventLoop running=True closed=False debug=False>
print(proxy.t)
<Thread(Thread-6, started 42484)>
这让我认为这种方法可能是错误的,而不是使用asyncio的正确方法
有人能解释一下吗?我对Python中的asyncio不太熟悉
谢谢
PS:我只能使用Python 3.4.3,因为您是从不同的线程调用的,而不是asyncio。async使用:
我同意您的方法可能是错误的-这里似乎有太多线程和异步的组合-但是缺少一些信息来建议满足您需求的最佳解决方案。缺少的主要部分是谁在调用get\u async以及它应该如何返回结果。我已经用asyncio.run\u coroutine\u threadsafe更新了我的答案