2009-08-04 10 views
5

¿Cuál es la forma recomendada para poner fin a las discusiones inesperadamente larga que se ejecutan en Python? No puedo usar SIGALRM, yahilos pitón de larga ejecución

hay que tener cierto cuidado si se utilizan ambos señales y los hilos en el mismo programa . Lo fundamental para recuerde en el uso de señales y los hilos simultáneamente es: realice siempre señal() operaciones en el hilo principal de ejecución. Cualquier hilo puede realizar una alarma(), getsignal(), pausa(), setitimer() o getitimer(); sólo el hilo principal se estableció un nuevo manejador de señales , y el hilo principal será el único en recibir señales (esto es impuesta por el módulo de Python señal , incluso si el subyacente implementación de hilos admite el envío señales a hilos individuales). Este significa que las señales no se pueden utilizar como un medio de inter-hilo communication.Use cerraduras lugar.

Actualización: cada hilo en mis bloques de casos: descarga una página web utilizando el módulo urllib2 y, a veces, la operación lleva demasiado tiempo en sitios extremadamente lentos. Es por eso que quiero poner fin a tales temas lentos

Respuesta

6

Dado que matar de manera abrupta un hilo que está en una llamada de bloqueo no es factible, un mejor enfoque, cuando sea posible, es evitar el uso de hilos en favor de otros mecanismos multitarea que no sufren de tales problemas.

Para el caso específico de OP (el trabajo de los hilos es descargar páginas web, y algunos hilos bloquean para siempre debido a sitios defectuosos), la solución ideal es twisted, como generalmente lo es para tareas de red. En otros casos, multiprocessing podría ser mejor.

De manera más general, cuando los hilos dan problemas insolubles, recomiendo cambiar a otros mecanismos multitarea en lugar de intentar medidas heroicas en el intento de hacer que los hilos realicen tareas para las cuales, al menos en CPython, no son adecuados.

1

Si usted está tratando de matar a un hilo cuyo código no tiene control sobre, depende si el hilo está en una llamada de bloqueo o no. En mi experiencia, si el hilo está bloqueando correctamente, no hay una forma recomendada y portátil de hacerlo.

He tropezado con esto cuando trato de trabajar con código en la biblioteca estándar (multiprocessing.manager Lo estoy mirando) con bucles codificados sin condición de salida: ¡agradable!

Existen algunas implementaciones de subprocesos intercatables (see here for an example), pero luego, si usted mismo tiene el control del código de subprocesamiento, debería poder escribirlos de manera que pueda intercalarlos con una variable de condición de algún tipo.

1

objetos Uso de sincronización y pedir al hilo para terminar. Básicamente, escriba el manejo cooperativo de esto.

Si comienza a tirar del hilo debajo del intérprete de python, pueden ocurrir todo tipo de cosas extrañas, y no es solo en Python tampoco, la mayoría de los tiempos de ejecución tienen este problema.

Por ejemplo, digamos que usted mata a un hilo después de que se ha abierto un archivo, no hay manera de que el archivo se cerrará hasta que la aplicación termina.

+0

El problema es cuando tienes un método que lleva demasiado tiempo (por ejemplo, urllib.read(), que en algunos casos ignora los tiempos de espera) que Me gustaría interrumpir. – kolinko

+1

Si ejecuta esa lectura en su propio hilo, ¿no puede simplemente dejar de esperarla? Eventualmente se completará/fallará/terminará y luego simplemente se muere? –

5

Como sugirió Alex Martelli, podría usar el módulo de multiprocesamiento. Es muy similar al módulo Threading, por lo que debería comenzar fácilmente. Su código podría ser así, por ejemplo:

import multiprocessing 

def get_page(*args, **kwargs): 
    # your web page downloading code goes here 

def start_get_page(timeout, *args, **kwargs): 
    p = multiprocessing.Process(target=get_page, args=args, kwargs=kwargs) 
    p.start() 
    p.join(timeout) 
    if p.is_alive(): 
     # stop the downloading 'thread' 
     p.terminate() 
     # and then do any post-error processing here 

if __name__ == "__main__": 
    start_get_page(timeout, *args, **kwargs) 

Por supuesto, debe obtener los valores de retorno del código de descarga de su página. Para eso, podría usar multiprocesamiento. Pipe o multiprocesamiento. Cola (u otras formas disponibles con multiprocesamiento). Hay más información, así como muestras que puede consultar en http://docs.python.org/library/multiprocessing.html.

Por último, el módulo de multiprocesamiento se incluye en python 2.6. También está disponible para Python 2.5 y 2.4 en PyPI (se puede utilizar

easy_install multiprocesamiento

)

o simplemente visitar PyPI y descargar e instalar los paquetes manualmente.

Nota: Me doy cuenta de que esto ha sido publicado hace un tiempo. Estaba teniendo un problema similar a esto y tropecé aquí y vi la sugerencia de Alex Martelli. Lo implementé para mi problema y decidí compartirlo. (Me gustaría dar las gracias a Alex por señalarme en la dirección correcta)

+0

Tengo exactamente el mismo problema, pero los Procesos no hacen exactamente el truco: requieren demasiada memoria y con 100 Procesos funcionando simultáneamente y 4GB de memoria ram me encuentro con dificultades. – kolinko

Cuestiones relacionadas