Créer des threads en python

177

J'ai un script et je veux qu'une fonction s'exécute en même temps que l'autre.

L'exemple de code que j'ai regardé:

import threading

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

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

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

J'ai du mal à faire fonctionner cela. Je préférerais que cela fonctionne en utilisant une fonction filetée plutôt qu'une classe.

Voici le script de travail:

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
la source

Réponses:

323

Vous n'avez pas besoin d'utiliser une sous-classe de Threadpour que cela fonctionne - jetez un œil à l'exemple simple que je poste ci-dessous pour voir comment:

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")

Ici, je montre comment utiliser le module de threading pour créer un thread qui invoque une fonction normale comme cible. Vous pouvez voir comment je peux lui transmettre les arguments dont j'ai besoin dans le constructeur de thread.

jkp
la source
J'ai essayé ceci. J'ai ajouté le script ci-dessus. Pourriez-vous me dire comment faire fonctionner la deuxième fonction parallèlement à la première. Merci
chrissygormley
6
@chrissygormley: join () bloque jusqu'à la fin du premier thread.
FogleBird
4
@chrissygormley: comme mentionné, joignez des blocs jusqu'à ce que le thread que vous rejoignez se termine, donc dans votre cas, démarrez un deuxième thread avec votre deuxième fonction comme cible pour exécuter les deux fonctions côte à côte, puis rejoignez éventuellement l'une d'elles si vous voulez juste attendre qu'ils soient terminés.
jkp
41
J'ai continué à lire exitingcomme exciting, ce que je pensais être plus approprié de toute façon.
Chase Roberts
42

Il y a quelques problèmes avec votre code:

def MyThread ( threading.thread ):
  • Vous ne pouvez pas sous-classe avec une fonction; seulement avec une classe
  • Si vous deviez utiliser une sous-classe, vous voudriez threading.Thread, pas threading.thread

Si vous voulez vraiment faire cela avec uniquement des fonctions, vous avez deux options:

Avec filetage:

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

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

Avec fil:

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

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

Doc pour thread.start_new_thread

Jorenko
la source
2
Le deuxième argument doit être un tuple pourthread.start_new_thread(function, args[, kwargs])
venkatvb
13

J'ai essayé d'ajouter une autre jointure (), et cela semble fonctionner. Voici le code

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
la source
3

Vous pouvez utiliser l' targetargument du Threadconstructeur pour passer directement une fonction qui est appelée à la place de run.

non-échantillonneur
la source
2

Avez-vous remplacé la méthode run ()? Si vous __init__avez passé outre , vous êtes-vous assuré d'appeler la base threading.Thread.__init__()?

Après avoir démarré les deux threads, le thread principal continue-t-il de fonctionner indéfiniment / bloque / joint sur les threads enfants afin que l'exécution du thread principal ne se termine pas avant que les threads enfants aient terminé leurs tâches?

Et enfin, obtenez-vous des exceptions non gérées?

Jeremy Brown
la source
Il n'y a pas d'exceptions non gérées et le thread principal doit s'exécuter pendant 30 minutes. Je n'ai pas passé outre __init__. Est-ce que run () est requis alors? Merci
chrissygormley
Je viens de réaliser que votre exemple est def MyThread ( threading.thread )... J'ai supposé qu'il s'agissait de définitions de classe. Si vous allez sous-classer threading.thread et initialiser l'objet thread avec target=Noneou omettre l' targetargument arg, alors une implémentation de run () est requise. Sinon, si vous souhaitez simplement exécuter une tâche simple dans un autre thread, consultez la réponse de jkp.
Jeremy Brown
0

Python 3 a la possibilité de lancer des tâches parallèles . Cela facilite notre travail.

Il a pour le pool de threads et le pool de processus .

Ce qui suit donne un aperçu:

Exemple 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)))

Un autre exemple

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
la source