Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.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
在Python2.7中,如果没有第三方包,如何实现异步请求_Python_Asynchronous_Python Requests - Fatal编程技术网

在Python2.7中,如果没有第三方包,如何实现异步请求

在Python2.7中,如果没有第三方包,如何实现异步请求,python,asynchronous,python-requests,Python,Asynchronous,Python Requests,我想要的是标题。背景是我有数千个请求要发送到程序中一个非常慢的Restful接口,其中除请求外,所有第三方包都不允许导入 多线程和多处理的速度仅限于GIL和运行程序的4核计算机 我知道您可以通过生成器在Python2.7中实现一个不完整的协同路由,并生成关键字,但我如何才能使用不完整的协同路由功能执行数千个请求呢 例子 首先,你从一个错误的前提出发 多处理的速度根本不受GIL的限制 多处理的速度仅受CPU限制工作的内核数量的限制,而您的情况并非如此。异步对于CPU受限的工作根本不起作用,因此多

我想要的是标题。背景是我有数千个请求要发送到程序中一个非常慢的Restful接口,其中除请求外,所有第三方包都不允许导入

多线程多处理的速度仅限于GIL和运行程序的4核计算机

我知道您可以通过生成器在Python2.7中实现一个不完整的协同路由,并生成关键字,但我如何才能使用不完整的协同路由功能执行数千个请求呢

例子
首先,你从一个错误的前提出发


  • 多处理的速度根本不受GIL的限制

  • 多处理的速度仅受CPU限制工作的内核数量的限制,而您的情况并非如此。异步对于CPU受限的工作根本不起作用,因此多处理将是异步的4倍,而不是更糟
  • 多线程处理的速度只受CPU绑定代码的GIL限制,而您的GIL又不是
  • 多线程的速度几乎不受内核数量的影响。如果您的代码是CPU绑定的,那么线程大部分会在单个内核上序列化。但是,异步在这里更糟糕,而不是更好
人们使用
async
的原因并不是因为它解决了这些问题;事实上,这只会让情况变得更糟。主要的优点是,如果您有大量的工作人员几乎不做任何工作,那么您可以将大量的等待时间安排在协同路由上,这比大量的等待线程或进程要便宜得多。第二个优点是,您可以将选择器循环绑定到调度程序循环,并消除协调它们的一些开销


其次,首先不能将
请求
asyncio
一起使用。它希望能够在套接字读取时阻止整个线程。有一个项目是围绕一个基于
asyncio
的传输适配器重写它,但它没有完成就被放弃了

通常的解决方法是在线程中使用它,例如,使用
run\u in\u executor
。但是,如果您正在做的唯一事情是
请求
,那么构建事件循环只是为了将事情分派给线程池执行器是愚蠢的;直接使用执行器即可


第三,我怀疑您是否真的需要有数千个请求并行运行。当然,尽管细节取决于您的服务、网络或任何瓶颈,但拥有一个线程池(例如,12或64个并行运行的请求,其他数千个请求在后面排队)几乎总是更有效的

处理数千个并发连接(因此也是工作者)通常只需要在服务器上完成。有时,您必须在从大量不同服务聚合数据的客户端上执行此操作。但是,如果您只使用一个服务,那么多并发性几乎没有任何好处


第四,如果您真的希望在Python2中使用基于协同程序的事件循环,到目前为止最简单的方法是使用
gevent
greenlets
或其他类似的库

是的,它们给你一个隐藏在你看不见的封面下的事件循环,以及一个“神奇”的协同程序,其中屈服发生在方法内部,比如
socket.send
Thread.join
,而不是通过
wait
yield from
显式可见,但好的一面是它们已经起作用了,事实上,这种魔力意味着它们可以处理
请求
,而您构建的任何东西都不会

当然,您不想使用任何第三方库。在Stackless或PyPy上构建类似于greenlets的东西非常容易;为CPython构建它需要做更多的工作。然后,您仍然需要像
gevent
那样进行所有的修补,使
sockets
之类的库像魔术一样工作,或者围绕显式的greenlet重写
请求


无论如何,如果您真的想在纯
yield
之上构建一个事件循环,您可以

在中,他列举了只使用
yield
的协程事件循环的例子,以及使用显式蹦床来
yield
的更好的例子和一个简单的网络驱动的例子。他甚至还编写了一个自动翻译程序,将代码从转换为Python3.1(当时还没有实现)

请注意,在蹦床上弹跳每一个屈服点都会降低效率。真的没办法。这是我们从该语言中获得
收益的一个很好的部分原因

但这只是带有一点玩具网络的调度程序部分。您仍然需要集成一个
选择器
循环,然后编写协同程序来替换所需的所有
套接字
函数。考虑代码< > AcsiCIO <代码>多长时间,当他知道Python的内部和外部,并从中得到<代码>收益时,就可以建立GuDo……但是你可以窃取他的大部分设计,所以不会那么糟糕。不过,这将是一个很大的工作

(哦,Python 2中没有
选择器
。如果你不关心Windows,那么从
选择
模块中构建你需要的部分是非常容易的,但是如果你关心Windows,那就需要做很多工作。)

请记住,因为
请求
与您的代码不兼容,所以您还需要重新实现大部分请求。或者,最好将
aiohttp
asyncio
移植到您的框架中

最后,我愿意给大家一个机会,结果不会像Python 3中的
aiohttp
或Python 2中的
gevent
上的
requests
那样有效,或者只是<
url_list = ["https://www.example.com/rest?id={}".format(num) for num in range(10000)]
results = request_all(url_list) # do asynchronously