Python请求:不要等待请求完成

oct*_*pus 16 python python-requests

在Bash中,可以通过追加在后台执行命令&.我怎么能在Python中做到这一点?

while True:
    data = raw_input('Enter something: ') 
    requests.post(url, data=data) # Don't wait for it to finish.
    print('Sending POST request...') # This should appear immediately.
Run Code Online (Sandbox Code Playgroud)

And*_*ter 21

我用multiprocessing.dummy.Pool.我在模块级别创建一个单例线程池,然后用于pool.apply_async(requests.get, [params])启动任务.

这个命令给了我一个未来,我可以无限期地添加到其他期货的列表中,直到我想收集全部或部分结果.

multiprocessing.dummy.Pool 反对所有逻辑和理由,是一个THREAD池而不是一个进程池.

示例(在Python 2和3中都有效,只要安装了请求):

from multiprocessing.dummy import Pool

import requests

pool = Pool(10) # Creates a pool with ten threads; more threads = more concurrency.
                # "pool" is a module attribute; you can be sure there will only
                # be one of them in your application
                # as modules are cached after initialization.

if __name__ == '__main__':
    futures = []
    for x in range(10):
        futures.append(pool.apply_async(requests.get, ['http://example.com/']))
    # futures is now a list of 10 futures.
    for future in futures:
        print(future.get()) # For each future, wait until the request is
                            # finished and then print the response object.
Run Code Online (Sandbox Code Playgroud)

请求将同时执行,因此运行所有这10个请求的时间不应超过最长的请求.这个策略只使用一个CPU核心,但这应该不是问题,因为几乎所有的时间都花在等待I/O上.

  • 您的解决方案看起来很有趣,但也令人困惑。什么是未来?什么是模块级别?你能提供一个工作示例吗? (4认同)
  • 我认为格式应该是`pool.apply_async(requests.post, [url], {'data': data})`。函数签名本质上是 (function_to_run, list_of_positional_args, dict_of_kwargs)。 (2认同)

kei*_*rth 20

这是一个hacky方式:

try:
    requests.get("http://127.0.0.1:8000/test/",timeout=0.0000000001)
except requests.exceptions.ReadTimeout: 
    pass
Run Code Online (Sandbox Code Playgroud)

  • 当我们不需要来自api的任何响应时,效果很好 (7认同)
  • 这种方法很hacky。在很多情况下它都会失败。 (3认同)
  • 您可以经常以这种方式丢失响应.问题是关于requests.post和它的身体也比一个简单的get更短,超时很短. (2认同)
  • 尝试此操作时,服务器未收到请求。任何想法? (2认同)
  • 即使既定的目标是解雇后忘记,这个解决方案也是不正确的。我们只需要[阅读文档](https://requests.readthedocs.io/en/latest/user/advanced/)。“超时值将应用于 **连接** 和 **读取** 超时。” 因此,人们报告服务器从未收到请求;此解决方案强制连接在 1e-10 秒内发生。正确的解决方案是“(无,0.0000000001)”。尽管如此,由于“requests”不正确地需要“Tuple[float, float]”,即使“TimeoutSauce”接受“None”作为任一参数,也可能会发生 linting 错误。 (2认同)

Rom*_*uin 6

根据文档,您应该移动到另一个库:

阻塞还是非阻塞?

使用默认传输适配器,请求不提供任何类型的非阻塞 IO。Response.content 属性将一直阻塞,直到整个响应被下载。如果您需要更多粒度,库的流功能(请参阅流请求)允许您一次检索更少量的响应。但是,这些调用仍然会阻塞。

如果您担心阻塞 IO 的使用,有很多项目将请求与 Python 的异步框架之一相结合。

两个很好的例子是 grequestsrequests-futures


Mun*_*ram 6

最简单和最Pythonic的解决方案使用threading

继续发送POST/GET或执行任何其他函数而不等待其完成的简单方法是使用内置 Python 模块threading

import threading
import requests

def send_req():
    requests.get("http://127.0.0.1:8000/test/")


for x in range(100):
    threading.Thread(target=send_req).start() # start's a new thread and continues. 

Run Code Online (Sandbox Code Playgroud)

其他重要特征threading

  • 您可以使用以下命令将这些线程变成守护进程thread_obj.daemon = True

  • 您可以继续等待一个完成执行,然后继续使用thread_obj.join()

  • thread_obj.is_alive()您可以使用bool: True/False检查线程是否处于活动状态

  • 您甚至可以通过以下方式检查活动线程数threading.active_count()

官方文档


Nem*_*ich 5

Andrew Gorcester的优雅解决方案。此外,无需使用期货,就可以使用callbackand error_callback属性(请参阅 doc)来执行异步处理:

def on_success(r: Response):
    if r.status_code == 200:
        print(f'Post succeed: {r}')
    else:
        print(f'Post failed: {r}')

def on_error(ex: Exception):
    print(f'Post requests failed: {ex}')

pool.apply_async(requests.post, args=['http://server.host'], kwargs={'json': {'key':'value'},
                        callback=on_success, error_callback=on_error))
Run Code Online (Sandbox Code Playgroud)