Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 需要一个中心代理来异步发送web请求,但如何将任务添加到其事件循环中_Python_Python 3.x_Python Asyncio - Fatal编程技术网

Python 需要一个中心代理来异步发送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

我希望实现一个代理类,该类由应用程序的其余部分用来异步发送web请求。我需要这个类,这样我就可以有一个中心点来控制流量,例如限制发送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())
这是我到目前为止的看法。。当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更新了我的答案