Categoria: Programacion Tema: Python Titulo: Threads en Python
Fecha del Tema: 2012-09-23 23:22:44Threads en Python El trabajo con threads se lleva a cabo en Python mediante el módulo thread. Este módulo es opcional y dependiente de la plataforma, y puede ser necesario, aunque no es común, recompilar el intérprete para añadir el soporte de threads. Además de thread, también contamos con el módulo threading que se apoya en el primero para proporcionarnos una API de más alto nivel, más completa, y orientada a objetos. El módulo threading se basa ligeramente en el modelo de threads de Java. El módulo threading contiene una clase Thread que debemos ex- tender para crear nuestros propios hilos de ejecución. El método run contendrá el código que queremos que ejecute el thread. Si queremos especificar nuestro propio constructor, este deberá llamar a threading. Thread.__init__(self) para inicializar el objeto correctamente. <? import threading class MiThread(threading.Thread): def __init__(self, num): threading.Thread.__init__(self) self.num = num def run(self): print â??Soy el hilo", self.num ?> Para que el thread comience a ejecutar su código basta con crear una instancia de la clase que acabamos de definir y llamar a su método start. El código del hilo principal y el del que acabamos de crear se ejecutarán de forma concurrente. <? print â??Soy el hilo principal" for i in range(0, 10): t = MiThread(i) t.start() t.join() ?> El método join se utiliza para que el hilo que ejecuta la llamada se bloquee hasta que finalice el thread sobre el que se llama. En este caso se utiliza para que el hilo principal no termine su ejecución antes que los hijos, lo cuál podrÃa resultar en algunas plataformas en la termina- ción de los hijos antes de finalizar su ejecución. El método join puede tomar como parámetro un número en coma flotante indicando el número máximo de segundos a esperar. Si se intenta llamar al método start para una instancia que ya se está ejecutando, obtendremos una excepción. La forma recomendada de crear nuevos hilos de ejecución consiste en extender la clase Thread, como hemos visto, aunque también es posible crear una instancia de Thread directamente, e indicar como parámetros del constructor una clase ejecutable (una clase con el método espe- cial __call__) o una función a ejecutar, y los argumentos en una tupla (parámetro args) o un diccionario (parámetro kwargs). <? import threading def imprime(num): print â??Soy el hilo", num print â??Soy el hilo principal" for i in range(0, 10): t = threading.Thread(target=imprime, args=(i, )) t.start() ?> Además de los parámetros target, args y kwargs también podemos pasar al constructor un parámetro de tipo cadena name con el nom- bre que queremos que tome el thread (el thread tendrá un nombre predeterminado aunque no lo especifiquemos); un parámetro de tipo booleano verbose para indicar al módulo que imprima mensajes sobre el estado de los threads para la depuración y un parámetro group, que por ahora no admite ningún valor pero que en el futuro se utilizará para crear grupos de threads y poder trabajar a nivel de grupos. Para comprobar si un thread sigue ejecutándose, se puede utilizar el método isAlive. También podemos asignar un nombre al hilo y con- sultar su nombre con los métodos setName y getName, respectivamente. Mediante la función threading.enumerate obtendremos una lista de los objetos Thread que se están ejecutando, incluyendo el hilo principal (podemos comparar el objeto Thread con la variable main_thread para comprobar si se trata del hilo principal) y con threading.activeCount podemos consultar el número de threads ejecutándose. Los objetos Thread también cuentan con un método setDaemon que toma un valor booleano indicando si se trata de un demonio. La utili- dad de esto es que si solo quedan threads de tipo demonio ejecutándo- se, la aplicación terminará automáticamente, terminando estos threads de forma segura. Por último tenemos en el módulo threading una clase Timer que he- reda de Thread y cuya utilidad es la de ejecutar el código de su método run después de un periodo de tiempo indicado como parámetro en su constructor. También incluye un método cancel mediante el que cancelar la ejecución antes de que termine el periodo de espera.
Threads en Python El trabajo con threads se lleva a cabo en Python mediante el módulo thread. Este módulo es opcional y dependiente de la plataforma, y puede ser necesario, aunque no es común, recompilar el intérprete para añadir el soporte de threads. Además de thread, también contamos con el módulo threading que se apoya en el primero para proporcionarnos una API de más alto nivel, más completa, y orientada a objetos. El módulo threading se basa ligeramente en el modelo de threads de Java. El módulo threading contiene una clase Thread que debemos ex- tender para crear nuestros propios hilos de ejecución. El método run contendrá el código que queremos que ejecute el thread. Si queremos especificar nuestro propio constructor, este deberá llamar a threading. Thread.__init__(self) para inicializar el objeto correctamente. <? import threading class MiThread(threading.Thread): def __init__(self, num): threading.Thread.__init__(self) self.num = num def run(self): print â??Soy el hilo", self.num ?> Para que el thread comience a ejecutar su código basta con crear una instancia de la clase que acabamos de definir y llamar a su método start. El código del hilo principal y el del que acabamos de crear se ejecutarán de forma concurrente. <? print â??Soy el hilo principal" for i in range(0, 10): t = MiThread(i) t.start() t.join() ?> El método join se utiliza para que el hilo que ejecuta la llamada se bloquee hasta que finalice el thread sobre el que se llama. En este caso se utiliza para que el hilo principal no termine su ejecución antes que los hijos, lo cuál podrÃa resultar en algunas plataformas en la termina- ción de los hijos antes de finalizar su ejecución. El método join puede tomar como parámetro un número en coma flotante indicando el número máximo de segundos a esperar. Si se intenta llamar al método start para una instancia que ya se está ejecutando, obtendremos una excepción. La forma recomendada de crear nuevos hilos de ejecución consiste en extender la clase Thread, como hemos visto, aunque también es posible crear una instancia de Thread directamente, e indicar como parámetros del constructor una clase ejecutable (una clase con el método espe- cial __call__) o una función a ejecutar, y los argumentos en una tupla (parámetro args) o un diccionario (parámetro kwargs). <? import threading def imprime(num): print â??Soy el hilo", num print â??Soy el hilo principal" for i in range(0, 10): t = threading.Thread(target=imprime, args=(i, )) t.start() ?> Además de los parámetros target, args y kwargs también podemos pasar al constructor un parámetro de tipo cadena name con el nom- bre que queremos que tome el thread (el thread tendrá un nombre predeterminado aunque no lo especifiquemos); un parámetro de tipo booleano verbose para indicar al módulo que imprima mensajes sobre el estado de los threads para la depuración y un parámetro group, que por ahora no admite ningún valor pero que en el futuro se utilizará para crear grupos de threads y poder trabajar a nivel de grupos. Para comprobar si un thread sigue ejecutándose, se puede utilizar el método isAlive. También podemos asignar un nombre al hilo y con- sultar su nombre con los métodos setName y getName, respectivamente. Mediante la función threading.enumerate obtendremos una lista de los objetos Thread que se están ejecutando, incluyendo el hilo principal (podemos comparar el objeto Thread con la variable main_thread para comprobar si se trata del hilo principal) y con threading.activeCount podemos consultar el número de threads ejecutándose. Los objetos Thread también cuentan con un método setDaemon que toma un valor booleano indicando si se trata de un demonio. La utili- dad de esto es que si solo quedan threads de tipo demonio ejecutándo- se, la aplicación terminará automáticamente, terminando estos threads de forma segura. Por último tenemos en el módulo threading una clase Timer que he- reda de Thread y cuya utilidad es la de ejecutar el código de su método run después de un periodo de tiempo indicado como parámetro en su constructor. También incluye un método cancel mediante el que cancelar la ejecución antes de que termine el periodo de espera.