Neste artigo vamos falar de Threads em Python. Antes de começar, preciso avisar que estou escrevendo enquanto pesquiso sobre o tema. Não atribua a este artigo autoridade maior do que ele merece. O objetivo dele é compartilhar o aprendizado do autor. Isto significa que o que é mostrado aqui está correto, mas não te dispensa de pesquisar em outras fontes.
Feitas as ressalvas, voltemos ao tema.
Explicando de forma grosseira, thread é uma forma de você não deixar seu programa ‘travar’ enquanto executa uma tarefa demorada. Usando thread, voce pode colocar essa tarefa para correr em paralelo, enquanto seu código segue; como uma bifurcação, mas dentro do mesmo processo, compartilhando o mesmo espaço de programa, como as variáveis e tudo o mais.
Há duas formas de você adicionar funcionalidades de threads ao seu código: com o módulo thread ou com a classe threading.Thread.
Com o módulo thread, você chama o método thread.start_new_thread(func, args), onde func é a função que você escreveu e que vai ser executada pela thread, e args é um tupla com os argumentos para a sua função.
O módulo threading é uma ‘extensão’ do módulo thread. Ele implementa a classe Thread e, entre outros, seu método start(). O método start() vai (não diretamente) chamar o método run() com start_new_thread(). Há também mais de uma forma de usar threading.Thread:
- criando uma instância de threading.Thread() ou
- criando uma classe que herda de threading.Thread e sobrescrevendo o método run().
Na primeira forma:
from threading import Thread
def minha_funcao(algumacoisa):
print algumacoisa
th=Thread( target=minha_funcao, args = ( 'qualquercoisa', ) )
th.start()
O construtor de Thread recebe, além de self, 6 argumentos (referência aqui), e entre eles:
- group: Deve ser sempre None, é reservado para uso em uma futura classe ThreadGroup;
- target: o método ou função que vai ser chamado em run();
- args: uma tupla com os argumentos que serão passados para a função em target.
Veja trecho do código de threading.py, localizado no meu sistema em /usr/lib/python2.5 .
Para ver onde fica o arquivo no seu sistema, veja o valor de threading.__file__
class Thread(_Verbose):
__initialized = False
# Need to store a reference to sys.exc_info for printing
# out exceptions when a thread tries to use a global var. during interp.
# shutdown and thus raises an exception about trying to perform some
# operation on/with a NoneType
__exc_info = _sys.exc_info
def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, verbose=None):
assert group is None, "group argument must be None for now"
_Verbose.__init__(self, verbose)
if kwargs is None:
kwargs = {}
self.__target = target
self.__name = str(name or _newname())
self.__args = args
self.__kwargs = kwargs
self.__daemonic = self._set_daemon()
self.__started = False
self.__stopped = False
self.__block = Condition(Lock())
self.__initialized = True
# sys.stderr is not stored in the class like
# sys.exc_info since it can be changed between instances
self.__stderr = _sys.stderr
Na segunda forma (herdando de threading.Thread), somente os métodos __init__() e run() podem ser sobrescritos.
# -.- coding: utf-8 -.-
from threading import Thread
class minhaThread(Thread):
# sobrescrevendo o método __init__()
def __init__(self, meu_argumento):
# o metodo __init__ da superclasse
# deve ser chamado para proceder
# com a inicialização
Thread.__init__(self)
self.atributo=meu_argumento
# sobrescrevendo o metodo run()
def run(self):
#insira seu codigo aqui
print 'patata'
Para executar a thread, você cria uma instância de minhaThread() e chama o método minhaThread.start().
thr = minhaThread( 'algum argumento' )
thr.start()
Não estenderemos por agora o artigo, e não haverá aqui nenhum exemplo “funcional” de utilização de threads.
Por enquanto, ficam as referências de pesquisa:
Understanding Threading in Python
Using threads in PyGTK
Python Library Reference – 15.3.6 Thread Objects