Acabo de jugar un poco con python y threads, y me di cuenta incluso de que en una secuencia de comandos multiproceso, las solicitudes de DNS son bloqueantes. Considere el siguiente script:¿El intérprete de Python bloquea las solicitudes de DNS multiproceso?
de enhebrar la importación de rosca toma importación
class Connection(Thread):
def __init__(self, name, url):
Thread.__init__(self)
self._url = url
self._name = name
def run(self):
print "Connecting...", self._name
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setblocking(0)
s.connect((self._url, 80))
except socket.gaierror:
pass #not interested in it
print "finished", self._name
if __name__ == '__main__':
conns = []
# all invalid addresses to see how they fail/check times
conns.append(Connection("conn1", "www.2eg11erdhrtj.com"))
conns.append(Connection("conn2", "www.e2ger2dh2rtj.com"))
conns.append(Connection("conn3", "www.eg2de3rh1rtj.com"))
conns.append(Connection("conn4", "www.ege2rh4rd1tj.com"))
conns.append(Connection("conn5", "www.ege52drhrtj1.com"))
for conn in conns:
conn.start()
No sé exactamente cuánto tiempo el tiempo de espera es, pero cuando se ejecuta este ocurre lo siguiente:
- sus temas comienzan y obtengo mis impresiones
- Cada xx segundos, un hilo muestra terminado, en lugar de todos a la vez
- T Los hilos terminan secuencialmente, no todos a la vez (tiempo de espera = ¡lo mismo para todos!)
Entonces, ¿mi única conjetura es que esto tiene que ver con el GIL? Obviamente, los hilos no realizan su tarea al mismo tiempo, solo se intenta una conexión a la vez.
¿Alguien sabe una forma de evitar esto?
(asyncore no ayuda, y yo preferiría no usar trenzado por ahora) ¿No es posible obtener este pequeño y sencillo acto realizado con Python?
Saludos, Tom
edición:
estoy en MacOSX, Acabo de dejar mi amigo ejecutar esto en Linux, y de hecho lo hace obtener los resultados que deseaba obtener. Su socket.connects() regresa de inmediato, incluso en un entorno sin hilos. E incluso cuando establece las tomas en el bloqueo y el tiempo de espera en 10 segundos, todos sus subprocesos terminan al mismo tiempo.
¿Alguien puede explicar esto?
has necesitado simplemente utilizando socket.getaddrinfo (anfitrión, puerto) para ver si eso tiene la misma limitación? Desafortunadamente no puedo replicar esto, porque es un problema de DNS. En la mayoría de los casos, debe obtener un "gaierror:" (-2, "Nombre o servicio no conocido") bastante rápido. – JimB
sí He intentado esto, y tiene la misma limitación. – Tom
Estoy bastante seguro de que OSX usa getaddrinfo de las librerías BSD, que probablemente tenga la restricción mencionada por a continuación. –
JimB