En mi script, requests.get
nunca regresa:
import requests
print ("requesting..")
# This call never returns!
r = requests.get(
"http://www.some-site.com",
proxies = {'http': '222.255.169.74:8080'},
)
print(r.ok)
¿Cuáles podrían ser las posibles razones? ¿Algún remedio? ¿Cuál es el tiempo de espera predeterminado que get
usa?
python
get
python-requests
Nawaz
fuente
fuente
proxies={'http': 'http://222.255.169.74:8080'}
. Esa podría ser la razón por la que no se completa sin un tiempo de espera.Respuestas:
El tiempo de espera predeterminado es
None
, lo que significa que esperará (se bloqueará) hasta que se cierre la conexión.¿Qué sucede cuando pasa un valor de tiempo de espera?
fuente
None
significa infinito (o "esperar hasta que se cierre la conexión"). Si me paso el tiempo de espera, ¡vuelve!print(requests.request.__doc__)
en IPython es más de lo que estaba buscando. Me preguntaba qué otros argumentos opcionalesrequest.get()
había.De la documentación de solicitudes :
Me pasa mucho que request.get () tarda mucho en regresar, incluso si
timeout
es de 1 segundo. Hay algunas formas de solucionar este problema:1. Usa la
TimeoutSauce
clase internaDe: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896
2. Utilice una bifurcación de solicitudes de kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout
De su documentación: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst
NOTA: Desde entonces, el cambio se ha combinado con el proyecto principal de Solicitudes .
3. Usando
evenlet
osignal
como ya se mencionó en la pregunta similar: tiempo de espera para solicitudes de Python. Obtener la respuesta completafuente
Quería un tiempo de espera predeterminado agregado fácilmente a un montón de código (asumiendo que el tiempo de espera resuelve su problema)
Esta es la solución que recogí de un ticket enviado al repositorio de solicitudes.
crédito: https://github.com/kennethreitz/requests/issues/2011#issuecomment-477784399
La solución son las últimas dos líneas aquí, pero muestro más código para un mejor contexto. Me gusta usar una sesión para reintentar el comportamiento.
entonces puedes hacer algo como esto:
fuente
Revisó todas las respuestas y llegó a la conclusión de que el problema aún existe. En algunos sitios, las solicitudes pueden colgarse infinitamente y el uso de multiprocesamiento parece ser excesivo. Aquí está mi enfoque (Python 3.5+):
ACTUALIZAR
Si recibe una advertencia de obsolescencia sobre el uso de conn_timeout y read_timeout, verifique cerca del final de ESTA referencia para saber cómo usar la estructura de datos ClientTimeout. Una forma sencilla de aplicar esta estructura de datos según la referencia vinculada al código original anterior sería:
fuente
Parchear la función "enviar" documentada solucionará este problema para todas las solicitudes, incluso en muchas bibliotecas dependientes y sdk. Cuando aplique parches a las bibliotecas, asegúrese de parchear las funciones compatibles / documentadas, no TimeoutSauce; de lo contrario, puede terminar perdiendo silenciosamente el efecto de su parche.
Los efectos de no tener ningún tiempo de espera son bastante graves, y el uso de un tiempo de espera predeterminado casi nunca puede romper nada, porque el propio TCP también tiene tiempos de espera predeterminados.
fuente
En mi caso, la razón de "request.get never returns" es porque el
requests.get()
intento de conectarme al host se resolvió con ipv6 ip primero . Si algo salió mal para conectar esa ip ipv6 y se atasca, entonces vuelve a intentar ipv4 ip solo si configuro explícitamentetimeout=<N seconds>
y alcanzo el tiempo de espera.Mi solución es parchear el python
socket
para ignorar ipv6 (o ipv4 si ipv4 no funciona), esta respuesta o esta respuesta funcionan para mí.Quizás se pregunte por qué funciona el
curl
comando, porquecurl
conecte ipv4 sin esperar a que se complete ipv6. Puede rastrear las llamadas al sistema de socket constrace -ff -e network -s 10000 -- curl -vLk '<your url>'
command. Para Python,strace -ff -e network -s 10000 -- python3 <your python script>
se puede usar el comando.fuente