tutorial threads thread manager manage example and python multithreading

threads - Anulando el threading de python.Thread.run()



python thread pool (6)

Dada la documentación de Python para Thread.run() :

Puede anular este método en una subclase. El método run () estándar invoca el objeto invocable pasado al constructor del objeto como argumento de destino, si lo hay, con argumentos secuenciales y de palabra clave tomados de los argumentos args y kwargs, respectivamente.

He construido el siguiente código:

class DestinationThread(threading.Thread): def run(self, name, config): print ''In thread'' thread = DestinationThread(args = (destination_name, destination_config)) thread.start()

Pero cuando lo ejecuto, recibo el siguiente error:

Exception in thread Thread-1: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 522, in __bootstrap_inner self.run() TypeError: run() takes exactly 3 arguments (1 given)

Parece que me falta algo obvio, pero los diversos ejemplos que he visto funcionan con esta metodología. Finalmente, estoy tratando de pasar la secuencia y el diccionario al hilo, si el Constructor no es el correcto, sino más bien crear una nueva función para establecer los valores antes de iniciar el hilo, estoy abierto a eso.

¿Alguna sugerencia sobre cómo lograr esto?


Usted define el método de ejecución para aceptar 3 argumentos, pero lo llama con un argumento (python lo llama con la referencia al objeto).

Necesitas pasar los argumentos para ejecutar en lugar de __init__ .

O haga que el método __init__ acepte los argumentos en su lugar.


Si desea mantener su enfoque orientado a objetos y también ha ejecutar argumentos, puede hacer lo siguiente:

import threading class Destination: def run(self, name, config): print ''In thread'' destination = Destination() thread = threading.Thread(target=destination.run, args=(destination_name, destination_config)) thread.start()

Como se mencionó anteriormente, también se puede hacer con partial

from functools import partial import threading class Destination: def run(self, name, config): print ''In thread'' destination = Destination() thread = threading.Thread(target=partial( destination.run, destination_name, destination_config)) thread.start()

La ventaja de hacer esto frente a un enfoque puramente funcional es que le permite mantener el mismo código existente orientado a objetos. El único cambio es tenerlo no subclase Thread, que no debería ser un gran problema, ya que por threading.Thread Documentación de threading.Thread :

solo anula los métodos init () y run () de esta clase

Si estaba anulando Thread para poder acceder al objeto thread desde dentro de su subclase, le recomendaría usar threading.currentThread () desde dentro de su objeto. De esta forma, segmenta el espacio de nombres del hilo del suyo y según el "Zen de Python" de Tim Peters:

Los espacios de nombres son una gran idea: ¡hagamos más de eso!


Para abordar la confusión sobre si un método run() anulado toma argumentos adicionales, aquí hay una implementación de un método run() anulado que hace lo mismo que el método heredado de threading.Thread .

Tenga en cuenta, esto solo para ver cómo se anularía run() ; no pretende ser un ejemplo significativo. Si todo lo que quiere hacer es invocar una función de destino con argumentos secuenciales y / o palabras clave, no es necesario tener una subclase; esto ha sido señalado, por ejemplo, en la respuesta de Jerub a esta pregunta.

El siguiente código es compatible con Python v2 y v3.

Aunque particularmente el acceso a los nombres de atributos mutilados en el código de Python 2 es feo, no conozco otra forma de acceder a estos atributos (hágamelo saber si conoce uno ...):

import sys import threading class DestinationThread(threading.Thread): def run(self): if sys.version_info[0] == 2: self._Thread__target(*self._Thread__args, **self._Thread__kwargs) else: # assuming v3 self._target(*self._args, **self._kwargs) def func(a, k): print("func(): a=%s, k=%s" % (a, k)) thread = DestinationThread(target=func, args=(1,), kwargs={"k": 2}) thread.start() thread.join()

Imprime (probado con Python 2.6, 2.7 y 3.4 en Windows 7):

func(): a=1, k=2


La documentación de threading.Thread puede parecer que implica que cualquier argumento posicional y de palabra clave sin usar se pasan a ejecutar. Ellos no son.

Cualquier args posicional adicional y kwargs palabra clave quedan atrapados por el método predeterminado threading.Thread.__init__ , pero ÚNICAMENTE se pasan a un método especificado utilizando target= keyword. NO se pasan al método run() .

De hecho, la documentación de Threading deja en claro que es el método run() predeterminado que invoca el método target= proporcionado con los kwargs atrapados y kwargs :

"Puede anular este método en una subclase. El método estándar run () invoca el objeto invocable pasado al constructor del objeto como el argumento de destino, si lo hay, con argumentos secuenciales y de palabra clave tomados de los argumentos args y kwargs, respectivamente".


Realmente no es necesario que subclass Thread. La única razón por la que la API admite esto es para que sea más cómodo para las personas que vienen de Java, donde esa es la única manera de hacerlo de manera sensata.

El patrón que recomendamos utilizar es pasar un método al constructor de subprocesos y simplemente llamar a .start() .

def myfunc(arg1, arg2): print ''In thread'' print ''args are'', arg1, arg2 thread = Thread(target=myfunc, args=(destination_name, destination_config)) thread.start()


Aquí hay un ejemplo de pasar argumentos usando threading y no extendiendo __init__ :

import threading class Example(threading.Thread): def run(self): print ''%s from %s'' % (self._Thread__kwargs[''example''], self.name) example = Example(kwargs={''example'': ''Hello World''}) example.start() example.join()

Y aquí hay un ejemplo usando mutliprocessing:

import multiprocessing class Example(multiprocessing.Process): def run(self): print ''%s from %s'' % (self._kwargs[''example''], self.name) example = Example(kwargs={''example'': ''Hello World''}) example.start() example.join()