Fila e Threads

Explicação

Queue

Em termos simples, uma fila é como uma linha de pessoas esperando para serem atendidas. As pessoas só podem entrar no final da fila e sair pelo começo. Da mesma forma, em uma fila de programação, as tarefas (ou "itens") só podem ser adicionadas ao final da fila e removidas do começo. Isso é conhecido como FIFO (First In, First Out), ou seja, o primeiro a entrar é o primeiro a sair.

Threads

Imagine que você tem uma grande quantidade de trabalhos que precisam ser feitos, mas cada trabalho leva algum tempo para ser concluído. Em vez de fazer todos os trabalhos um após o outro (o que seria muito lento), você decide dividir o trabalho entre vários funcionários. Cada funcionário pode trabalhar em um trabalho de cada vez, e assim todos os trabalhos são concluídos mais rápido.

No mundo da programação, esses "trabalhos" são chamados de "tarefas" e os "funcionários" são chamados de "threads". O ThreadPoolExecutor é como um gerente que organiza esses funcionários e distribui as tarefas entre eles. Ele cria um grupo de threads e gerencia a execução das tarefas para que todas sejam concluídas de maneira eficiente.

Demonstração

Simplificada - Queue

  • Importa a Fila

    from queue import Queue
    
  • Inicializa a fila

    fila = Queue()
    
  • Insere um valor na fila

    fila.put('qualquer valor')
    
  • Retira um valor da fila para processar

    valor = fila.get()
    

Simplificada - ThreadPoolExecutor

  • Importa o Executor de Threads

    from concurrent.futures import ThreadPoolExecutor
    
  • Gera alguma varíavel de interáveis (filas, listas, tuples, etc...)

    itens_x = [1, 2, 3, 4, 5]
    
  • Define a função que irá processar os valores

    def funcao_y(x):
        pass
    
  • Executa os processos de acordo com quantidade de Threads estipulada

    with ThreadPoolExecutor(max_workers=3) as executor:
        resultados = [executor.submit(funcao_y, valor) for valor in itens_x]
    

Completa - Prática

  • Importa as bibliotecas necessárias para o exemplo

    from queue import Queue # Funcionalidade da fila
    import requests # Efetua requisições HTTP
    import xml.etree.ElementTree as ET # Permite analisar arquivos XMLs
    import json # Permite analisar arquivos JSON
    from concurrent.futures import ThreadPoolExecutor # Funcionalidade das Threads
    
  • Instancia a fila para ser preenchida

    fila = Queue()
    
  • Adiciona moedas para dentro da fila (função qsize() mostra a quantidade de itens na fila)

    for moeda in ['USD', 'EUR', 'JPY', 'GBP', 'ARS']:
        fila.put(moeda)
    
    print(fila.qsize())
    # resultado: 5
    
  • Cria função para fazer a coleta da cotação para diferentes moedas

    def coleta_cotacao(moeda, datas):
        cotacoes = {moeda: []} # Dicionario vazio para popular futuramente com as cotações
        siglas = {'USD': '220', 'EUR': '978',
                'JPY': '470', 'GBP': '540',
                'ARS': '706'} # Dicionário contendo a sigla e qual o código da moeda
        for data in datas: # Para cada data informada, fazer 1 interação
            retorno = requests.get(f'https://www3.bcb.gov.br/bc_moeda/rest/converter/1/1/{siglas[moeda]}/790/{data}') # Faz requisição da cotação
            root = ET.fromstring(retorno.text) # Converte o retorno XML em algo modificável pelo Python
            cotacoes[moeda].append({data: root.text}) # Adiciona data e o valor da cotação na chave contendo a sigla
        with open(f'cotacoes_{moeda}.json', 'w') as arqv: # Salva um arquivo .json final
            json.dump(cotacoes, arqv)
    
  • Instancia as "threads" para cada uma rodar uma moeda

    with ThreadPoolExecutor(max_workers=5) as executor: # Gerenciador de contexto instanciado para executar as threads
        results = [executor.submit(coleta_cotacao,
                                fila.get(),
                                ['2024-02-09', '2024-02-08', '2024-02-07', '2024-02-06',
                                    '2024-02-05', '2024-02-02', '2024-02-01', '2024-01-31',
                                    '2024-01-30', '2024-01-29']) for _ in range(5)] # List Comprehension interando uma "queue" com data padrões