2014-11-19 2 views
7

В Bash можно выполнить команду в фоновом режиме, добавив &. Как я могу сделать это в Python?Запросы на 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. 
+0

В отличие от проблем параллелизма CPU переплете в Python, это, возможно, может быть решена с отдельным потоком, или использование 'multiprocessing.dummy' для пула потоков , –

ответ

12

Я использую 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. 

Запросы будут выполняться параллельно, поэтому запуск все десять из этих запросов должно занимать не более длинный один. Эта стратегия будет использовать только одно ядро ​​ЦП, но это не должно быть проблемой, потому что почти все время будет потрачено на ожидание ввода-вывода.

+1

Ваше решение выглядит интересным, но и запутанным. Какое будущее? Каков уровень модуля? Не могли бы вы привести рабочий пример? – octosquidopus

+0

@octosquidopus добавил пример ответа –

+0

Ваш пример хорошо работает, но это не совсем то, что я пытаюсь сделать. Вместо отправки одновременных запросов я хотел бы отправлять их по одному, но не блокируя остальную часть кода. Мой пример теперь должен быть менее двусмысленным. – octosquidopus

1

Согласно doc, вы должны перейти в другую библиотеку:

Blocking Or Non-Blocking?

With the default Transport Adapter in place, Requests does not provide any kind of non-blocking IO. The Response.content property will block until the entire response has been downloaded. If you require more granularity, the streaming features of the library (see Streaming Requests) allow you to retrieve smaller quantities of the response at a time. However, these calls will still block.

If you are concerned about the use of blocking IO, there are lots of projects out there that combine Requests with one of Python’s asynchronicity frameworks.

Two excellent examples are grequests and requests-futures .

+0

Я пробовал запросы-фьючерсы, но он терпит неудачу в 'csrf = s.cookies ['csrftoken']'. – octosquidopus

1

Если вы можете написать код, который будет выполняться отдельно в виде отдельной программы питона, here является возможным решением на основе subprocessing ,

В противном случае вы можете найти полезный this question и связанный с ним ответ: трюк заключается в использовании библиотеки потоков для запуска отдельного потока, который будет выполнять разделенную задачу.

Предостережение с обоими подходами может состоять из числа элементов (то есть количества потоков), которыми вы должны управлять. Если item s в parent слишком много, вы можете приостановить каждую партию элементов, пока, по крайней мере, некоторые потоки не закончатся, но я считаю, что такое управление является нетривиальным.

Для более сложного подхода вы можете использовать подход, основанный на актерах, я сам не использовал this library, но я думаю, что это могло бы помочь в этом случае.

-1

Вот Hacky способ сделать это:

try: 
    requests.get("http://127.0.0.1:8000/test/",timeout=0.0000000001) 
except requests.exceptions.ReadTimeout: 
    pass 
+2

Вы можете потерять ответ таким образом часто. Вопрос состоял в том, что request.post и его тело также более хрупкие с очень коротким таймаутом, чем простой get. – hynekcer

Смежные вопросы