Crear hilos en python

177

Tengo un script y quiero que una función se ejecute al mismo tiempo que la otra.

El código de ejemplo que he visto:

import threading

def MyThread (threading.thread):
    # doing something........

def MyThread2 (threading.thread):
    # doing something........

MyThread().start()
MyThread2().start()

Tengo problemas para que esto funcione. Preferiría poner esto en marcha utilizando una función enhebrada en lugar de una clase.

Este es el script de trabajo:

from threading import Thread

class myClass():

    def help(self):
        os.system('./ssh.py')

    def nope(self):
        a = [1,2,3,4,5,6,67,78]
        for i in a:
            print i
            sleep(1)


if __name__ == "__main__":
    Yep = myClass()
    thread = Thread(target = Yep.help)
    thread2 = Thread(target = Yep.nope)
    thread.start()
    thread2.start()
    thread.join()
    print 'Finished'
chrissygormley
fuente

Respuestas:

323

No necesita usar una subclase de Threadpara hacer que esto funcione; eche un vistazo al sencillo ejemplo que estoy publicando a continuación para ver cómo:

from threading import Thread
from time import sleep

def threaded_function(arg):
    for i in range(arg):
        print("running")
        sleep(1)


if __name__ == "__main__":
    thread = Thread(target = threaded_function, args = (10, ))
    thread.start()
    thread.join()
    print("thread finished...exiting")

Aquí muestro cómo usar el módulo de subprocesos para crear un subproceso que invoca una función normal como destino. Puedes ver cómo puedo pasarle cualquier argumento que necesite en el constructor de hilos.

jkp
fuente
He intentado esto He agregado script arriba. ¿Podría decirme cómo hacer que la segunda función se ejecute junto a la primera? Gracias
chrissygormley
66
@chrissygormley: une () bloques hasta que termine el primer hilo.
FogleBird
44
@chrissygormley: como se mencionó, unir los bloques hasta que finalice el hilo que está uniendo, por lo que en su caso, comience un segundo hilo con su segunda función como objetivo para ejecutar las dos funciones una al lado de la otra, y opcionalmente una a una de ellas si solo quieres esperar hasta que terminen.
jkp
41
Seguí leyendo exitingcomo exciting, lo que pensé que era más apropiado de todos modos.
Chase Roberts el
42

Hay algunos problemas con su código:

def MyThread ( threading.thread ):
  • No puedes subclasificar con una función; solo con una clase
  • Si fuera a utilizar una subclase, desearía enhebrar.

Si realmente desea hacer esto solo con funciones, tiene dos opciones:

Con roscado:

import threading
def MyThread1():
    pass
def MyThread2():
    pass

t1 = threading.Thread(target=MyThread1, args=[])
t2 = threading.Thread(target=MyThread2, args=[])
t1.start()
t2.start()

Con hilo:

import thread
def MyThread1():
    pass
def MyThread2():
    pass

thread.start_new_thread(MyThread1, ())
thread.start_new_thread(MyThread2, ())

Doc. Para thread.start_new_thread

Jorenko
fuente
2
El segundo argumento debe ser una tupla parathread.start_new_thread(function, args[, kwargs])
venkatvb
13

Intenté agregar otra unión (), y parece que funcionó. Aquí hay código

from threading import Thread
from time import sleep

def function01(arg,name):
    for i in range(arg):
        print(name,'i---->',i,'\n')
        print (name,"arg---->",arg,'\n')
        sleep(1)

def test01():
    thread1 = Thread(target = function01, args = (10,'thread1', ))
    thread1.start()
    thread2 = Thread(target = function01, args = (10,'thread2', ))
    thread2.start()
    thread1.join()
    thread2.join()
    print ("thread finished...exiting")

test01()
GGG
fuente
3

Puede usar el targetargumento en el Threadconstructor para pasar directamente una función que se llama en lugar de run.

muestreador
fuente
2

¿Anuló el método run ()? Si anulaste __init__, ¿te aseguraste de llamar a la base threading.Thread.__init__()?

Después de iniciar los dos subprocesos, ¿el subproceso principal continúa funcionando indefinidamente / bloquea / une en los subprocesos secundarios para que la ejecución del subproceso principal no finalice antes de que los subprocesos secundarios completen sus tareas?

Y finalmente, ¿está recibiendo alguna excepción no controlada?

Jeremy Brown
fuente
No hay excepciones no controladas y el subproceso principal debe ejecutarse durante 30 minutos. No anulé __init__. ¿Se requiere run () entonces? Gracias
chrissygormley
Me acabo de dar cuenta de que tu ejemplo es def MyThread ( threading.thread )... Supuse que esas eran definiciones de clase. Si va a subclasificar threading.thread e inicializar el objeto thread con target=Noneu omitir el targetargumento, entonces se requiere una implementación de run (). De lo contrario, si solo desea ejecutar una tarea simple en otro hilo, vea la respuesta de jkp.
Jeremy Brown,
0

Python 3 tiene la facilidad de lanzar tareas paralelas . Esto facilita nuestro trabajo.

Tiene para la agrupación de subprocesos y la agrupación de procesos .

Lo siguiente da una idea:

Ejemplo de ThreadPoolExecutor

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

Otro ejemplo

import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()
Jeril
fuente