Verificando a velocidade da Internet com a biblioteca Requests em multiprocessamento

Bom tempo, queridos residentes de Habr!



Hoje falaremos como, a partir da ideia de medir a velocidade, foi criado um script para fazer o upload de um arquivo de imagem e devolvê-lo ao servidor, com o cálculo do tempo de execução de cada uma das funções e o cálculo da velocidade.



Vou começar com uma lista de bibliotecas usadas:



  • importar os
  • do pool de importação de multiprocessamento
  • tempo de importação
  • importar pandas como pd
  • pedidos de importação


Em seguida, precisamos de uma lista de servidores, preferi criar um dicionário para isso:



server_list = [
    {
        'server_id': 3682,
        'download': 'http://moscow.speedtest.rt.ru:8080/speedtest/random7000x7000.jpg',
        'upload': 'http://moscow.speedtest.rt.ru:8080/speedtest/upload.php'
    }
]


Vamos escrever a primeira função:



def download(id, path):
    start = time.time()
    file_name = str(id) + str(path.split('/')[-1])
    try:
        r = requests.get(path, stream=True, timeout=5)
    except:
        return 0
    size = int(r.headers.get('Content-Length', 0))
    with open(file_name, 'wb') as f:
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)

    end = time.time()
    duration = end - start
    sp = (((size * 8) / 1024) / 1024) / duration

    return sp


Agora mais sobre o que está acontecendo.



A função tem um horário de início e um horário de término (em segundos), dos quais mais tarde obtemos o tempo de vida. Escreva a id do servidor e o nome da imagem no nome do arquivo (para que não haja conflitos ao carregar de fontes múltiplas). Em seguida, fazemos uma solicitação GET, obtemos o tamanho do arquivo (em bytes) e salvamos no disco. Traduzimos bytes em bits, um pouco mais de magia com fórmulas e na saída temos uma velocidade em MBit / s.



A próxima função é fazer upload de um arquivo para o servidor:



def upload(id, path):
    start = time.time()
    file_name = str(id) + 'random7000x7000.jpg'
    with open(file_name, 'rb') as f:
        files = {'Upload': (file_name, f.read())}
    try:
        requests.post(path, files=files)
    except:
        return 0
    size = os.path.getsize(file_name)
    end = time.time()
    duration = end - start
    sp = (((size * 8) / 1024) / 1024) / duration

    return sp


O princípio é o mesmo aqui, apenas pegamos um arquivo de uma pasta local e o enviamos com uma solicitação POST.



Nossa próxima tarefa é obter dados das duas funções anteriores. Vamos escrever mais uma função:



def test_f(conn, server):
    speed_download = download(server['server_id'], server['download'])
    speed_upload = upload(server['server_id'], server['upload'])
    return server['server_id'], speed_download, speed_upload
    


A única coisa que resta a fazer é adicionar multiprocessamento com um pool e uma função de mapa paralelo :



def main():
    pool = Pool()
    data = pool.map(test_f, server_list)

    df = pd.DataFrame(data, columns=['Server', 'Download', 'Upload'])
    print(df)

    pool.close()
    pool.join()




if __name__ == '__main__':
    main()


O script está pronto para uso, para a comodidade da saída, usei a biblioteca pandas. Você também pode colocar a saída no banco de dados e coletar estatísticas para análise.



Obrigado pela atenção!



UPD: corrigiu exceções, fez correções no trabalho de multiprocessamento (substituiu o loop por uma função paralela), adicionou um tempo limite para a solicitação GET



All Articles