2014-11-19 9 views
7

W Bash można wykonywać polecenia w tle, dodając &. Jak mogę to zrobić w Pythonie?Żądania w pythonie: Nie czekaj na zakończenie żądania

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

przeciwieństwie do kwestii współbieżności CPU-bound w Pythonie, to mogłaby być rozwiązana w osobnym wątku, albo użycie 'multiprocessing.dummy' dla puli wątków . –

Odpowiedz

12

Używam multiprocessing.dummy.Pool. Tworzę pojedynczą pulę wątków na poziomie modułu, a następnie używam pool.apply_async(requests.get, [params]) do uruchomienia zadania.

To polecenie daje mi przyszłość, którą mogę dodawać do listy z innymi przyszłymi kontraktami w nieskończoność, dopóki nie będę chciał zebrać wszystkich lub niektórych wyników.

multiprocessing.dummy.Pool jest, wbrew wszelkim logikom i powodom, pulą THREAD, a nie puli procesów.

Przykład (działa zarówno w Pythonie 2 i 3, o ile jest zainstalowany wnioski):

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. 

Wnioski będą realizowane równocześnie, tak działa cały dziesięć z tych wniosków nie powinno trwać dłużej niż najdłuższy jeden. Ta strategia będzie używać tylko jednego rdzenia procesora, ale nie powinno to stanowić problemu, ponieważ prawie cały czas będzie spędzać czas oczekiwania na wejścia/wyjścia.

+1

Twoje rozwiązanie wygląda interesująco, ale jest też mylące. Jaka jest przyszłość? Jaki jest poziom modułu? Czy możesz podać przykład pracy? – octosquidopus

+0

@octosquidopus dodano przykład, aby odpowiedzieć –

+0

Twój przykład działa dobrze, ale nie jest to dokładnie to, co próbuję zrobić. Zamiast wysyłać równoczesne żądania, chciałbym wysłać je pojedynczo, ale bez blokowania reszty kodu. Mój przykład powinien być mniej dwuznaczny. – octosquidopus

1

Według doc, należy przejść do innej biblioteki:

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

Próbowałem request-futures, ale nie udało się to w 'csrf = s.cookies ['csrftoken']'. – octosquidopus

1

Jeśli można napisać kod wykonywany oddzielnie w osobnym programie Pythona, here jest możliwe rozwiązanie oparte na subprocessing .

W przeciwnym razie może się okazać przydatna this question i odpowiednia odpowiedź: Sztuką jest użycie biblioteki wątków do uruchomienia osobnego wątku, który wykona oddzielone zadanie.

Ograniczeniem z obydwoma podejściami może być liczba elementów (to znaczy liczba wątków), którymi trzeba zarządzać. Jeśli item s w parent jest zbyt wiele, możesz rozważyć zatrzymanie każdej partii elementów, dopóki przynajmniej niektóre wątki nie zostaną zakończone, ale myślę, że ten rodzaj zarządzania nie jest trywialny.

Aby uzyskać bardziej wyrafinowane podejście, można użyć podejścia opartego na aktorach, sam nie używałem this library, ale myślę, że mogłoby w tym pomóc.

-1

Oto hacky sposób to zrobić:

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

W ten sposób często można utracić odpowiedź. Pytanie dotyczyło request.post, a jego ciało jest również bardziej kruche z bardzo krótkim czasem oczekiwania niż zwykłe pobranie. – hynekcer

Powiązane problemy