Vérification de la vitesse Internet avec la bibliothèque Requests en multitraitement

Bon temps, chers habitants de Habr!



Aujourd'hui, nous allons parler de comment, à partir de l'idée de mesurer la vitesse, un script a été créé pour télécharger un fichier image et le renvoyer au serveur, avec le calcul du temps d'exécution de chacune des fonctions et le calcul de la vitesse.



Je vais commencer par une liste des bibliothèques utilisées:



  • importer le système d'exploitation
  • à partir du pool d'importation multitraitement
  • temps d'importation
  • importer des pandas en tant que pd
  • demandes d'importation


Ensuite, nous avons besoin d'une liste de serveurs, j'ai préféré créer un dictionnaire pour cela:



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'
    }
]


Écrivons la première fonction:



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


Maintenant plus sur ce qui se passe.



La fonction a une heure de début et une heure de fin (en secondes), à partir desquelles nous obtenons plus tard la durée de vie. Nous écrivons l'id du serveur et le nom de l'image dans le nom du fichier (fait pour qu'il n'y ait pas de conflits lors du chargement à partir de plusieurs sources). Ensuite, nous faisons une requête GET, obtenons la taille du fichier (en octets) et l'enregistrons sur le disque. Nous traduisons les octets en bits, un peu plus de magie avec des formules et en sortie nous avons une vitesse en MBit / s.



La fonction suivante consiste à télécharger un fichier sur le serveur:



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


Le principe est le même ici, seulement nous prenons un fichier d'un dossier local et l'envoyons avec une requête POST.



Notre tâche suivante consiste à récupérer les données des deux fonctions précédentes. Écrivons encore une fonction:



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
    


La seule chose à faire est d'ajouter le multitraitement avec un pool et une fonction de carte parallèle :



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


Le script est prêt à être utilisé, pour la commodité de la sortie, j'ai utilisé la bibliothèque pandas. Vous pouvez également placer la sortie dans la base de données et collecter des statistiques pour analyse.



Merci de votre attention!



UPD: correction des exceptions, correction du travail de multiprocessing (remplacement de la boucle par une fonction parallèle), ajout d'un timeout pour la requête GET



All Articles