Forum Programmation.python Exercices à résoudre en Python

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
-13
3
jan.
2019

Bonjour tous,

J'ai des exos à faire en Python (Python 3). Suis bloqué. Sollicite votre aide svp…

Je travaille sur la base d'un fichier txt comportant des données de logs associés à un site internet pendant une période de deux jours.Chaque ligne du fichier représente la demande d'accès d'un hôte (visiteur) à une ressource du site en question (une page, une image, etc.). Nous disposons des infos suivantes concernant cette demande: l'heure précise, le code retournépar le serveur site à cette demande (404 si la ressource demandée n'existe pas, 200 indique que la demande a été bien traitée) et la taille de la réponse fournie par le serveur (donc la taille de la ressource quand le code retourné est 200)… Le jeu de données est disponible sur la page http://ita.ee.lbl.gov/html/contrib/EPA-HTTP.html

il m'a été demandé de répondre aux questions suivantes (SANS UTILISER DE LIBRAIRIES)…

  1. Combien de requêtes d’accès (de lignes) sont de type GET ?
  2. Fournissez les statistiques de nombre d’accès par code retourné par le serveur (ie., le nombre d’accès avec un code 200, le nombre d’accès avec le code 404, …).
  3. Combien de requêtes ont été effectuées par heure et par jour ?
  4. Combien d’utilisateurs uniques ont accédé au site par heure ?
  5. Pour la journée du 30, combien de requêtes de type GET ont cherché à accéder à un fichier contenu dans le répertoire docs ?
  6. Combien de requêtes concernent des fichiers de type image (jpeg, jpg, png, etc.?
  7. Qui a le plus accédé au site durant cette période ?
  8. Quelle est la taille moyenne des images demandées par les utilisateurs? Attention, si un utilisateur souhaite accéder à une image mais que le code retourné est 400, alors la taille de la ressource (la dernière valeur de la ligne) n’indique pas la taille de l’image.
  • # Show the code

    Posté par  . Évalué à 9.

    Salut,

    il m'a été demandé de répondre aux questions suivantes

    Bin pas à nous :-)

    On pourrait bien t'aider sur un début de code mais pas vraiment sur une implémentation complète.

    Donc montre le code déjà fait.

    Sinon, il devrait y avoir des prestataires prêts à prendre à la journée. Toute heure commencée est dûe ceci étant.

    Bon courage :-)

    Matricule 23415

  • # Mon code

    Posté par  . Évalué à -1. Dernière modification le 04 janvier 2019 à 08:46.

    Question 1
    ```
    count = 0
    chaine = "GET" # Texte à rechercher

    Ouverture du fichier en mode lecture

    fichier = open("C:/Users/CMBEAC/Desktop/M2_FOAD/2018/PYTHON/Projet/data_project.txt","r")
    for ligne in fichier: # Pour toute ligne dans le fichier
    if chaine in ligne: # Si le caractère à rechercher s’y trouve, le compter.
    count = count + 1
    print(count)
    ```

    • [^] # Re: Mon code

      Posté par  . Évalué à 1. Dernière modification le 04 janvier 2019 à 09:16.

      Attention à l'indentation,

      count = 0
      chaine = "GET" # Texte à rechercher
      fichier = open("C:/Users/CMBEAC/Desktop/M2_FOAD/2018/PYTHON/Projet/data_project.txt","r")
      for ligne in fichier: # Pour toute ligne dans le fichier
          if chaine in ligne: # Si le caractère à rechercher s’y trouve, le compter.
              count = count + 1
      print(count)

      Tu as le nombre de get sur le lien qui te permet de vérifier si ton code n'est pas déconnant

      Par contre je vois déjà un risque à ce code :
      Admettons que tu aies une requête POST "POST […]GET[…]"
      Le get est au milieu d'une chaine de caractère (par exemple j'ai vu un "budget" dans le fichier des requête (certes pas dans un POST mais ça peut très bien arrivé), et bien ton code va considérer cette requête comme un get car il y a un GET dans la ligne.

      • [^] # Re: Mon code

        Posté par  . Évalué à 1.

        Bonjour Marco,
        J'ai vérifié. Le nombre de requêtes que mon code me donne équivaut bien à ce qui figure sur le lien (46014)… C'est rassurant.

        • [^] # Re: Mon code

          Posté par  . Évalué à 2.

          oui ton code peut très bien marcher dans ton cas mais admettons que ton fichier ait par exemple la ligne suivante

          ix-stp-fl1-20.ix.netcom.com [30:05:36:57] "POST /cgi-bin/GET/waisgate/134.67.99.11=earth1=210=/usr1/comwais/indexes/HTDOCS=gopher%40earth1=0.00=:free HTTP/1.0" 200 27418

          Quel est le comportement attendu (incrémenter count ou pas) ? Quelle est le comportement réel ?

          C'est bien que ça marche dans l'exemple donné mais il faut faire très attention aux cas imprévus. Si tu raisonnes comme ça pour un code (pour un fichier ça fonctionne donc ca va marcher pour tous les fichiers imaginables), tu vas vite avoir des retours utilisateurs avec des bugs. Et si tu n'as pas fais la démarche d'où sont les risques, bon courage pour corriger les bugs.

  • # Mon code Question 2

    Posté par  . Évalué à 0.

    Question 2

    count = 0
    chaine = "200" # Code à rechercher
    fichier = open("C:/Users/PYTHON/Projet/data_project.txt","r")
    for ligne in fichier:   # Pour toute ligne dans le fichier
        if chaine in ligne: # Si le code à rechercher s’y trouve, le compter.
            count += 1
    print(count)
    

    Pour cette question, j'ai fait les scripts pour chaque code (200, 400, 404, etc.). Mais à y regarder de près, il faut faire un seul script pour tous ces codes… Et là, je n'ai pas pu…

    • [^] # Re: Mon code Question 2

      Posté par  . Évalué à 1.

      Salut,

      Pour cette question, j'ai fait les scripts pour chaque code (200, 400, 404, etc.). Mais à y regarder de près, il faut faire un seul script pour tous ces codes… Et là, je n'ai pas pu…

      Peut-être que c'est parce que ton script est mal pensé ?

      Il y a un « truc » à savoir sur l'informatique, c'est que c'est un outil de fainéant. Donc il y a des structures de données pour faire à peu près tout.

      Moi j'aurais fait quelque chose comme ça (pseudo-code à traduire en python) :

      dictionnaire = {} # on initialise le dictionnaire à rien
      fichier = ouvrir("le fichier")
      pour ligne dans fichier:
          code = découper(ligne, ",")[le bon indexe]
          si le dictionnaire ne contient pas le code
              initialiser l'entrée à 1
          sinon
              incrémenter la valeur associée au code
      afficher(dictionnaire)

      Matricule 23415

      • [^] # Re: Mon code Question 2

        Posté par  . Évalué à 0.

        d = {}
        for c in fichier:
            reply_code = fichier.split(ligne, ",")[2] # clé
            if reply_code in d: d [reply_code] += 1
            else: d [reply_code] = 1
        print (d)
        

        Salut KAOS,

        Voilà ce que j'ai pu faire… Tu peux m'aider à l'améliorer?

        • [^] # Re: Mon code Question 2

          Posté par  . Évalué à 1.

          Salut,

          Tu peux m'aider à l'améliorer ?

          Je suis mauvais en python, mais à partir d'une base qui fonctionne ou presque, d'autres pourront potentiellement t'aider. :-)

          Matricule 23415

        • [^] # Re: Mon code Question 2

          Posté par  . Évalué à 4.

          je me lance, dans la foulée de kaos.

          Le code que tu as mis dans ton commentaire ne peut pas faire ce que tu veux parce que tu fais ta boucle for sur une variable 'c', mais ensuite, dans la boucle, tu travailles avec la variable 'ligne'. En fonction du code du reste de ton script, soit tu as une erreur de syntaxe, soit la variable ligne est initialisée ailleurs, et tu obtiens un résultat, mais c'est pas du tout ce que tu veux.

          Vu la taille des scripts que tu dois faire pour ces exos, c'est pas les quelques lignes d'import et d'ouverture de fichiers qui vont rendre tes commentaires illisibles, alors je te conseille de copier tes scripts complets en commentaire, ça nous évitera de devoir spéculer sur ce que tu fais ;)

          Je te rappelle (ou t'indique) que tu peux utiliser des balises pour copier du code sur linuxfr, ça permet de préserver l'indentation et ça ajoute de la coloration syntaxique, c'est le Bien.

          Pour ces lignes là:

              if reply_code in d: d [reply_code] += 1
              else: d [reply_code] = 1

          En python, sauf erreur de ma part, il n'est généralement pas recommandé d'écrire l'instruction sur la même ligne que le test. Si le if a une clause else, c'est même fortement déconseillé. Sur le plan cosmétique, ça devrait plus ressembler à:

              if reply_code in d:
                  d [reply_code] += 1
              else:
                  d [reply_code] = 1

          J'aurais même plutôt écrit:

              if d.has_key(reply_code)

          parce que ça fait une recherche dans un index plutôt qu'un parcours de la liste de toutes les clefs, donc ça doit être plus performant, mais ce n'est pas une différence fondamentale.

          Un truc un peu dommage pour les affectations de ce genre là, c'est qu'on va tester à chaque fois si la clef est présente avant d'incrémenter la valeur dans le dictionnaire, mais en fait, ce n'est utile que pour la première affectation de chaque clef. Du coup, à une époque, il n'était pas rare de voir des trucs comme ça:

              try:
                  d[reply_code] += 1
              except KeyError:
                  d[reply_code] = 1

          C'est à dire qu'on incrémente directement la valeur dans le dictionnaire, et on traite l'exception quand la clef n'est pas présente (c'est à dire seulement la première fois qu'on incrémente chaque clef). Sur des petits volumes, le coût de traitement des exceptions est possiblement plus élevé que de tester à chaque éléments à traiter, mais sur des gros volumes, ça peut amener des gains de performances significatifs.

          Mais il y a mieux ! Tu peux utiliser un defaultdict qui permet de définir une fonction à appeler quand on cherche à accéder à une clef absente du dictionnaire. Je ne met pas le code, parce que ça serait plus intéressant pour toi de l'écrire (et ça permet de découvrir lambda). Ci dessous, une session interactive pour illustrer un peu comment ça marche:

          $ python3
          Python 3.7.2 (default, Jan  3 2019, 02:55:40) 
          [GCC 8.2.0] on linux
          Type "help", "copyright", "credits" or "license" for more information.
          >>> from collections import defaultdict
          >>> dd = defaultdict(lambda: 0)
          >>> len(dd) # le dictionnaire est bien vide
          0
          >>> dd[200] # mais quand on veut la valeur d'une clef absente, on n'a pas d'erreur
          0
          >>> dd[200] += 1 # on incrémente
          >>> len(dd) # notre dictionnaire contient bien un couple (clef, valeur) maintenant
          1
          >>> dd.items() # et c'est ce que l'on attendait
          dict_items([(200, 1)])
          • [^] # Re: Mon code Question 2

            Posté par  . Évalué à 4.

            Au temps pour moi, has_key est une méthode des dictionnaire en Python2, mais pas en Python3. Et en fait, la syntaxe 'in' est mieux. Donc oubliez cet alinéa de mon commentaire précédente

  • # Question 3

    Posté par  . Évalué à -1. Dernière modification le 04 janvier 2019 à 14:05.

    Voici ce que j'ai fait pour la question 3:
    ```

    def comptereq_jh (fic):
    d = {}
    for f in fic:
    date = f[1] # clé
    if date in d: d [date] += 1
    else: d [date] = 1
    return (d)

    dico_date = comptereq_jh (fic)
    print(dico_date)>
    ```

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.