Zbieram statystyki na temat listy stron internetowych i dla uproszczenia używam zapytań. Oto mój kod:
data=[]
websites=['http://google.com', 'http://bbc.co.uk']
for w in websites:
r= requests.get(w, verify=False)
data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) )
Teraz chcę requests.get
wygasnąć po 10 sekundach, aby pętla nie utknęła.
Ta kwestia była przedmiotem zainteresowania przed zbyt ale żadna z odpowiedzi są czyste. Będę za to nagradzać, aby uzyskać dobrą odpowiedź.
Słyszałem, że być może nieużywanie próśb jest dobrym pomysłem, ale w takim razie jak mam uzyskać oferty żądań miłych rzeczy. (te w krotce)
python
timeout
python-requests
Kiarash
źródło
źródło
Odpowiedzi:
A co z korzystaniem z eventletu? Jeśli chcesz przekroczyć limit czasu żądania po 10 sekundach, nawet jeśli odbierane są dane, ten fragment będzie działał dla Ciebie:
źródło
eventlet.monkey_patch()
wymagane?socket
moduł wymaga łatki małpy, więc przynajmniej będziesz potrzebowaćeventlet.monkey_patch(socket=True)
requests.get('https://github.com', timeout=5)
Ustaw parametr limitu czasu :
Dopóki nie ustawisz
stream=True
tego żądania, spowodujerequests.get()
to przekroczenie limitu czasu wywołania, jeśli połączenie trwa dłużej niż dziesięć sekund lub jeśli serwer nie wyśle danych przez więcej niż dziesięć sekund.źródło
AKTUALIZACJA: https://requests.readthedocs.io/en/master/user/advanced/#timeouts
W nowej wersji
requests
:Jeśli określisz jedną wartość limitu czasu, na przykład:
Wartość limitu czasu zostanie zastosowana zarówno
connect
doread
limitów czasu, jak i do limitów czasu. Określ krotkę, jeśli chcesz ustawić wartości osobno:Jeśli serwer zdalny działa bardzo wolno, możesz nakazać Requests, aby czekały wiecznie na odpowiedź, przekazując None jako wartość limitu czasu, a następnie pobierając filiżankę kawy.
Moja stara (prawdopodobnie nieaktualna) odpowiedź (która została opublikowana dawno temu):
Istnieją inne sposoby rozwiązania tego problemu:
1. Użyj
TimeoutSauce
klasy wewnętrznejOd: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896
2. Użyj rozwidlenia żądań z kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout
Z jego dokumentacji: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst
kevinburke zażądał scalenia go z głównym projektem żądań, ale nie został jeszcze zaakceptowany.
źródło
this won't work for you use-case
. Miał na myśli to, że nie działa ze strumieniem mp3, którego chce inny facet.timeout = int(seconds)
Ponieważ
requests >= 2.4.0
możesz użyćtimeout
argumentu, tj .:Uwaga:
źródło
Aby utworzyć limit czasu, możesz użyć sygnałów .
Najlepszym sposobem rozwiązania tego przypadku jest prawdopodobnie
try-except-finally
bloku.Oto przykładowy kod:
Istnieją pewne zastrzeżenia:
Ale wszystko jest w standardowej bibliotece Pythona! Poza importem funkcji uśpienia jest to tylko jeden import. Jeśli zamierzasz używać limitów czasu w wielu miejscach, możesz łatwo umieścić wyjątek TimeoutException, _timeout i sygnalizację w funkcji i po prostu to wywołać. Lub możesz stworzyć dekorator i umieścić go na funkcjach, zobacz odpowiedź połączoną poniżej.
Możesz również ustawić go jako „menedżera kontekstu”, aby używać go z
with
instrukcją:Jedną możliwą wadą tego podejścia menedżera kontekstu jest to, że nie możesz wiedzieć, czy kod faktycznie przekroczył limit czasu, czy nie.
Źródła i zalecana lektura:
źródło
Wypróbuj to żądanie z limitem czasu i obsługą błędów:
źródło
Ustaw
stream=True
i używajr.iter_content(1024)
. Tak,eventlet.Timeout
jakoś mi się to nie udaje.Dyskusja jest tutaj https://redd.it/80kp1h
źródło
Może to być przesada, ale kolejka zadań rozproszonych Celery ma dobrą obsługę limitów czasu.
W szczególności możesz zdefiniować miękki limit czasu, który po prostu wywołuje wyjątek w twoim procesie (abyś mógł wyczyścić) i / lub sztywny limit czasu, który kończy zadanie, gdy limit czasu zostanie przekroczony.
Pod okładkami stosuje się to samo podejście do sygnałów, jak w poście „przed”, ale w bardziej użyteczny i łatwiejszy w zarządzaniu sposób. A jeśli lista monitorowanych witryn internetowych jest długa, może przydać się jej główna funkcja - wszelkiego rodzaju sposoby zarządzania wykonywaniem dużej liczby zadań.
źródło
python-requests
ale zhttplib
(używany przez żądania dla Pythona 2.7). Pakiet przekazuje wszystko, co dotyczytimeout
bezpośrednio do httplib. Myślę, że nic nie może zostać naprawione w żądaniu, ponieważ proces może pozostać przez długi czas w httplib.Uważam, że możesz korzystać
multiprocessing
z pakietu innej firmy i nie polegać na nim:Przekazany do limitu czasu
kwargs
jest limit czasu, aby uzyskać żadnej odpowiedzi z serwera, argumenttimeout
jest limit czasu, aby uzyskać pełną odpowiedź.źródło
timeout = (limit czasu połączenia, limit czasu odczytu danych) lub podaj pojedynczy argument (limit czasu = 1)
źródło
ten kod działa dla socketError 11004 i 10060 ......
źródło
Pomimo pytania o żądania, uważam, że jest to bardzo łatwe dzięki pycurl CURLOPT_TIMEOUT lub CURLOPT_TIMEOUT_MS.
Nie wymaga gwintowania ani sygnalizacji:
źródło
Jeśli korzystasz z opcji,
stream=True
możesz to zrobić:Rozwiązanie nie wymaga sygnałów ani przetwarzania wieloprocesowego.
źródło
Jeszcze jedno rozwiązanie (pobrane z http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads )
Przed przesłaniem możesz sprawdzić rozmiar zawartości:
Ale bądź ostrożny, nadawca może ustawić nieprawidłową wartość w polu odpowiedzi „content-length”.
źródło
Jeśli do tego dojdzie, utwórz wątek watchdog, który po 10 sekundach zepsuje stan wewnętrzny żądań, np .:
Zauważ, że w zależności od bibliotek systemowych możesz nie być w stanie ustawić ostatecznego terminu rozpoznawania nazw DNS.
źródło
Cóż, wypróbowałem wiele rozwiązań na tej stronie i nadal miałem do czynienia z niestabilnością, przypadkowymi zawieszeniami, słabą wydajnością połączeń.
Teraz używam Curl i jestem bardzo zadowolony z jego funkcji „maksymalnego czasu” i globalnych wyników, nawet przy tak słabej implementacji:
Tutaj zdefiniowałem maksymalny parametr czasu 6 sekund, obejmujący zarówno czas połączenia, jak i przesyłania.
Jestem pewien, że Curl ma fajne powiązanie Pythona, jeśli wolisz trzymać się składni Pythona :)
źródło
Istnieje pakiet o nazwie timeout-decorator , którego można użyć do przekroczenia limitu czasu dowolnej funkcji Pythona.
Wykorzystuje podejście sygnalizacyjne, które sugerują niektóre odpowiedzi. Alternatywnie możesz powiedzieć mu, aby używał przetwarzania wieloprocesowego zamiast sygnałów (np. Jeśli jesteś w środowisku wielowątkowym).
źródło
Używam żądań 2.2.1, a Eventlet nie działa dla mnie. Zamiast tego mogłem użyć gevent timeout, ponieważ gevent jest używany w mojej służbie dla gunicorn.
Należy pamiętać, że gevent.timeout.Timeout nie podlega ogólnej obsłudze wyjątków. Więc albo jawnie przechwyć
gevent.timeout.Timeout
lub przekaż inny wyjątek do użycia w ten sposób:with gevent.Timeout(5, requests.exceptions.Timeout):
chociaż żaden komunikat nie jest przekazywany, gdy ten wyjątek jest zgłaszany.źródło
Wymyśliłem bardziej bezpośrednie rozwiązanie, które jest wprawdzie brzydkie, ale rozwiązuje prawdziwy problem. Trochę to wygląda tak:
Możesz przeczytać pełne wyjaśnienie tutaj
źródło
timeout
parametr dorequests.get()
bez brzydkich obejść 2- chociaż oba nie ograniczą całkowitego limitu czasu w przeciwieństwie doeventlet.Timeout(10)