<packing> 182 Interface Gráfica <property name="x">167</property> <property name="y">61</property> </packing> </child> <child> <widget class="GtkButton" id="btn_fechar"> <property name="width_request">100</property> <property name="height_request">29</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="label" translatable="yes">_Fechar</property> <property name="use_underline">True</property> <property name="response_id">0</property> <signal name="clicked" handler="on_btn_fechar_clicked"/> </widget> <packing> <property name="x">272</property> <property name="y">61</property> </packing> </child> <child> <widget class="GtkEntry" id="ntr_cmd"> <property name="width_request">365</property> <property name="height_request">29</property> <property name="visible">True</property> <property name="can_focus">True</property> </widget> <packing> <property name="x">9</property> <property name="y">14</property> </packing> </child> <child> <widget class="GtkCheckButton" id="chk_shell"> <property name="width_request">136</property> <property name="height_request">29</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="label" translatable="yes">_Janela de texto</property> <property name="use_underline">True</property> <property name="response_id">0</property> <property name="draw_indicator">True</property> </widget> <packing> <property name="x">11</property> <property name="y">59</property> </packing> </child> </widget> </child> </widget> Interface Gráfica 183 </glade-interface> Além do Glade, também existe o Gaspacho56, outro construtor de interfaces que também gera arquivos XML no padrão do Glade. Funcionalidades associadas a interface gráfica podem ser obtidas usando outros módulos, como o pySystray57, que implementa a funcionalidade que permite que o aplicativo use a bandeja de sistema no Windows. 56 Disponível em: http://gazpacho.sicem.biz/. 57 Endereço na internet: http://datavibe.net/~essiene/pysystray/. 184 Threads Threads Uma thread é uma linha de execução que compartilha sua área de memória com outras linhas, ao contrário do processo tradicional, que possui apenas uma linha com área de memória própria. O uso de threads oferece algumas vantagens em relação aos processos convencionais: ▪ Consomem menos recursos de máquina. ▪ Podem ser criadas e destruídas mais rapidamente. ▪ Podem ser chaveadas mais rapidamente. ▪ Podem se comunicar com outras threads de forma mais fácil. É comum utilizar threads para: ▪ Processamento paralelo, em casos como atender várias conexões em processos servidores. ▪ Executar operações de I/O assíncronas, por exemplo: enquanto o usuário continua interagindo com a interface enquanto a aplicação envia um documento para a impressora. ▪ Operações de I/O em paralelo. Processo Thread 1 Thread 2 Thread 3 Thread 1 Tempo Thread 4 Threads 185 Em Python, o módulo da biblioteca padrão threading provê classes de alto nível de abstração e usa o módulo thread, que implementa as rotinas de baixo nível e que geralmente não é usado diretamente. Exemplo com o módulo threading: # -*- coding: latin1 -*- """ Exemplo de uso de threads """ import os import time import threading class Monitor(threading.Thread): """ Classe de monitoramento usando threads """ def __init__(self, ip): """ Construtor da thread """ # Atributos para a thread self.ip = ip self.status = None # Inicializador da classe Thread threading.Thread.__init__(self) def run(self): """ Código que será executado pela thread """ # Execute o ping ping = os.popen('ping -n 1 %s' % self.ip).read() if 'Esgotado' in ping: self.status = False else: self.status = True if __name__ == '__main__': # Crie uma lista com um objeto de thread para cada IP monitores = [] for i in range(1, 11): ip = '10.10.10.%d' % i 186 Threads monitores.append(Monitor(ip)) # Execute as Threads for monitor in monitores: monitor.start() # A thread principal continua enquanto # as outras threads executam o ping # para os endereços da lista # Verifique a cada segundo # se as threads acabaram ping = True while ping: ping = False for monitor in monitores: if monitor.status == None: ping = True break time.sleep(1) # Imprima os resultados no final for monitor in monitores: if monitor.status: print '%s no ar' % monitor.ip else: print '%s fora do ar' % monitor.ip Saída: 10.10.10.1 no ar 10.10.10.2 no ar 10.10.10.3 no ar 10.10.10.4 fora do ar 10.10.10.5 no ar 10.10.10.6 fora do ar 10.10.10.7 no ar 10.10.10.8 no ar 10.10.10.9 no ar 10.10.10.10 no ar É importante observar que, quando o processo morre, todas as suas threads terminam. Processamento distribuído 187 Processamento distribuído Geralmente a solução para problemas que requerem muita potência computacional é a utilização de máquinas mais poderosas, porém esta solução é limitada em termos de escalabilidade. Uma alternativa é dividir os processos da aplicação entre várias máquinas que se comunicam através de uma rede, formando um cluster ou um grid. A diferença básica entre cluster e grid é que o primeiro tem como premissa de projeto ser um ambiente controlado, homogêneo e previsível, enquanto o segundo é geralmente heterogêneo, não controlado e imprevisível. Um cluster é um ambiente planejado especificamente para processamento distribuído, com máquinas dedicadas em um lugar adequado. Um grid se caracteriza pelo uso de estações de trabalho que podem estar em qualquer lugar. Os modelos mais comuns de cluster: ▪ computacional. ▪ de recursos. ▪ de aplicação ou híbrido. O modelo computacional tem como objetivo usar processadores e memória dos Híbrido A B C D Computacional A B C D O servidor faz o escalonamento das tarefas para as estações. Qualquer máquina pode atuar como cliente e servidor. 188 Processamento distribuído equipamentos envolvidos para obter mais potência computacional. A implementação geralmente utiliza um sistema escalonador de filas (metascheduler), que realiza o agendamento das tarefas a serem processados pelos nós (máquinas que compõem o modelo), com isso a operação tende a ser contínua, com interação reduzida com os usuários. Um exemplo conhecido é o SETI@home58. O cluster de recursos é usado para armazenar informações em um grupo de computadores, tanto para obter mais performance de recuperação de dados quanto para expandir a capacidade de armazenamento. Este modelo pode ser usado para prover infra-estrutura para aplicações ou para atender requisições feitas de forma interativa por usuários. Entre os serviços que podem operar desta