Criando Threads em python

177

Eu tenho um script e quero que uma função seja executada ao mesmo tempo que a outra.

O código de exemplo que eu olhei:

import threading

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

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

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

Estou tendo problemas para fazer isso funcionar. Eu preferiria fazer isso usando uma função de thread em vez de uma classe.

Este é o script de trabalho:

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
fonte

Respostas:

323

Você não precisa usar uma subclasse de Threadpara fazer esse trabalho - dê uma olhada no exemplo simples que estou postando abaixo para ver como:

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

Aqui, mostro como usar o módulo de encadeamento para criar um encadeamento que invoca uma função normal como destino. Você pode ver como eu posso passar quaisquer argumentos necessários no construtor de threads.

jkp
fonte
Eu tentei isso. Eu adicionei o script acima. Você poderia me dizer como executar a segunda função ao lado da primeira. Obrigado
chrissygormley
6
@chrissygormley: join () blocks até o primeiro thread terminar.
FogleBird 25/05
4
@chrissygormley: como mencionado, junte blocos até que o thread que você está juntando termine; portanto, no seu caso, inicie um segundo thread com sua segunda função como destino para executar as duas funções lado a lado e, opcionalmente, junte uma delas se você só quer esperar até que terminem.
Jkp
41
Continuei lendo exitingcomo exciting, o que achei mais apropriado de qualquer maneira.
Perseguição Roberts
42

Existem alguns problemas com o seu código:

def MyThread ( threading.thread ):
  • Você não pode subclassificar com uma função; somente com classe
  • Se você fosse usar uma subclasse, desejaria threading.Thread, not threading.thread

Se você realmente deseja fazer isso apenas com funções, tem duas opções:

Com rosqueamento:

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

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

Com rosca:

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
fonte
2
O segundo argumento deve ser uma tupla parathread.start_new_thread(function, args[, kwargs])
venkatvb
13

Tentei adicionar outro join (), e parece que funcionou. Aqui está o 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
fonte
3

Você pode usar o targetargumento no Threadconstrutor para transmitir diretamente uma função que é chamada em vez de run.

unholysampler
fonte
2

Você substituiu o método run ()? Se você cancelou __init__, não se esqueça de ligar para a base threading.Thread.__init__()?

Após iniciar os dois threads, o thread principal continua a funcionar indefinidamente / bloqueia / ingressa nos threads filhos, para que a execução do segmento principal não termine antes que os segmentos filhos concluam suas tarefas?

E, finalmente, você está recebendo alguma exceção não tratada?

Jeremy Brown
fonte
Não há exceções não tratadas e o segmento principal deve ser executado por 30 minutos. Eu não substitui __init__. É necessário executar () então? Obrigado
chrissygormley
Acabei de perceber que seu exemplo é def MyThread ( threading.thread )... Supus que essas fossem definições de classe. Se você for subclassificar threading.thread e inicializar o objeto de encadeamento com target=Noneou omitir o targetarg, será necessária uma implementação de run (). Caso contrário, se você quiser executar uma tarefa simples em outro segmento, consulte a resposta do jkp.
Jeremy Brown
0

O Python 3 tem a facilidade de iniciar tarefas paralelas . Isso facilita nosso trabalho.

Possui para pool de threads e pool de processos .

A seguir, é apresentado um insight:

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

Outro exemplo

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
fonte