Se connecter

Informatique

Programmation

Sujet : [Python] Implémenter gestion d'erreur
1
NBKL
Niveau 10
22 juin 2017 à 12:09:53

Bonjour tout le monde, j'ai un petit script me permettant de récupérer le nombre de connectés sur différents forums de JVC. Sauf que cette nuit, j'ai eu une erreur et n'ayant rien mis en place il s'est arrêté tout net et ma machine a tourné pour rien. pendant plus de 10 heures :hap:

J'ai donc un peu réfléchit à une sorte de gestion des erreurs qui dès lors je n'arrive pas à accéder à la page cela réessaie au bout d'un certain temps. Mais je ne sais pas du temps comment l'implémenter correctement. J'en ai déjà fait un (petit) mais dans ce schéma là je ne sais pas comment le faire. Je pense juste qu'il faudrait que je recupère le code de réponse HTTP via getcode et que cette gestion se fasse dans la fonction "recup_co" :(

Voici ma classe :

class Forum():

	def __init__(self, forum, url_forum):
		self.forum = forum
		self.url_forum = url_forum

	def add_to_database(self): #ajout au fichier de la BD, la date et le nb_co
		connection = sqlite3.connect("database.db")
		c = connection.cursor()
		self.now = datetime.datetime.today()
		self.text = "INSERT INTO {0}(datetime, nb_co) VALUES('{1}', '{2}')".format(self.forum, self.now, self.recup_co())
		print(self.forum, self.recup_co())
		c.execute(self.text)
		connection.commit()
		connection.close()
		sleep(5)

	def recup_co(self):
		self.page_html = str(urlopen(self.url_forum).read()) # stockage du contenu de la page dans une variable

		self.page = BeautifulSoup(self.page_html, 'html.parser') 
		self.resultat = self.page.select(".nb-connect-fofo")

		self.nb_co = str(self.resultat) #stockage de la ligne avec le nombre de co

		self.nb_co = self.nb_co[:-27] #modification de la ligne pour ne garder que le nb de co
		self.nb_co = self.nb_co[31:]
		
		return self.nb_co

Ca fait vraiment quémandeur de code, mais je ne sais pas comment procéder :hap:
Merci d'avoir lu et de votre aide potentielle :hap:

Au passage, si vous avez des commentaires sur mon code je suis preneur de tout :hap:

Blaff4
Niveau 10
22 juin 2017 à 23:03:37

Quelques remarques vite fait sur ton code :

  • Utilise un logger grâce au module logging à la place des print() pour ainsi avoir un fichier qui te donneras des informations utiles lorsque tu feras du debug.
  • Met ton main() dans un try / except de sorte à savoir d'où vient l'erreur la prochaine fois (à combiner avec le logger).
  • Tu pourrais utiliser la bibliothèque requests au lieu de urllib.request, c'est beaucoup plus user-friendly.
  • Pas besoin de parenthèses après la définition de ta classe, class Forum: suffit.
  • Tu n'as pas changé la façon dont tu récupère le code en utilisant une regex ou .split() à la place de self.nb_co[:-27], pourtant quelqu'un te l'avait conseillé sur ton ancien topic. :hap:
  • Tu n'as pas besoin d'assigner toutes tes fonctions à ton objet : self.nb_co, self.now, self.text, self.page_html, self.page, self.resultat sont superflus puisqu'il vont changer très souvent, il ne décrivent pas ton forum intrinsèquement, et ils ne sont utilisés nulle part ailleurs que dans ta méthode.
  • Tu devrais convertir ton nb_co en int avant de le retourner, plutôt qu'en str.

Sinon, concernant ta question initiale, personnellement je le mettrai en dehors de la fonction recup_co. :ok:
Ça me paraît plus logique et libre de laisser à la fonction appelante le choix de la politique :

  • Réessayer ?
  • Si oui, combien de fois ?
  • Attendre quelques secondes ?
  • Afficher un message d'erreur ?

Donc je ferais quelque chose comme ça :

while True:
    try:
        forum.add_to_database()
    except URLError:
        print("Une erreur est survenue lors de l'ouverture de l'URL.")
        sleep(5)
NBKL
Niveau 10
24 juin 2017 à 22:04:12

Le 22 juin 2017 à 23:03:37 Blaff4 a écrit :
Quelques remarques vite fait sur ton code :

  • Utilise un logger grâce au module logging à la place des print() pour ainsi avoir un fichier qui te donneras des informations utiles lorsque tu feras du debug.
  • Met ton main() dans un try / except de sorte à savoir d'où vient l'erreur la prochaine fois (à combiner avec le logger).
  • Tu pourrais utiliser la bibliothèque requests au lieu de urllib.request, c'est beaucoup plus user-friendly.
  • Pas besoin de parenthèses après la définition de ta classe, class Forum: suffit.
  • Tu n'as pas changé la façon dont tu récupère le code en utilisant une regex ou .split() à la place de self.nb_co[:-27], pourtant quelqu'un te l'avait conseillé sur ton ancien topic. :hap:
  • Tu n'as pas besoin d'assigner toutes tes fonctions à ton objet : self.nb_co, self.now, self.text, self.page_html, self.page, self.resultat sont superflus puisqu'il vont changer très souvent, il ne décrivent pas ton forum intrinsèquement, et ils ne sont utilisés nulle part ailleurs que dans ta méthode.
  • Tu devrais convertir ton nb_co en int avant de le retourner, plutôt qu'en str.

Sinon, concernant ta question initiale, personnellement je le mettrai en dehors de la fonction recup_co. :ok:
Ça me paraît plus logique et libre de laisser à la fonction appelante le choix de la politique :

  • Réessayer ?
  • Si oui, combien de fois ?
  • Attendre quelques secondes ?
  • Afficher un message d'erreur ?

Donc je ferais quelque chose comme ça :

while True:
    try:
        forum.add_to_database()
    except URLError:
        print("Une erreur est survenue lors de l'ouverture de l'URL.")
        sleep(5)

Salut, merci de ta réponse. j'en prends compte pas de soucis :hap: Dès demain je vais mettre tout ça en œuvre :ok:

Par contre quand tu parles de faire :

while True:
    try:
        forum.add_to_database()
    except URLError:
        print("Une erreur est survenue lors de l'ouverture de l'URL.")
        sleep(5)

J'ai en tout 4 instances :

def main():
	dixhuit_vingtcinq = Forum("dixhuit_vingtcinq", "http://www.jeuxvideo.com/forums/0-51-0-1-0-1-0-blabla-18-25-ans.htm")
	moins_quinze = Forum("moins_quinze", "http://www.jeuxvideo.com/forums/0-15-0-1-0-1-0-blabla-moins-de-15-ans.htm")
	quinze_dixhuit = Forum("quinze_dixhuit", "http://www.jeuxvideo.com/forums/0-50-0-1-0-1-0-blabla-15-18-ans.htm")
	overwatch = Forum("overwatch", "http://www.jeuxvideo.com/forums/0-33972-0-1-0-1-0-overwatch.htm")
	while(True):
		dixhuit_vingtcinq.add_to_database()
		moins_quinze.add_to_database()
		quinze_dixhuit.add_to_database()
		overwatch.add_to_database()
		sleep(30)
main()

Ce qui veut dire, on est bien d'accord, qu'il faut que je mette les 4 dans le même try ?

Blaff4
Niveau 10
24 juin 2017 à 23:45:16

Nope, généralement il faut mieux minimiser le code dans un try afin d'avoir une gestion d'erreur plus fine et ainsi localiser plus précisément le problème.
En plus, si tu faisais ça et que le 18-25 était bugué alors les autres forums ne seraient jamais testés bien qu'ils puissent peut-être être accessibles, eux.

Personnellement, je regrouperai mes forums dans une liste et j'itérerai en boucle à travers afin de pouvoir tester un par un chacun d'eux. :ok:

forums = [dixhuit_vingtcinq, moins_quinze, quinze_dixhuit, overwatch]

while True:
    for forum in forums:
        try:
            forum.add_to_database()
        except URLError:
            print("Une erreur est survenue lors de l'ouverture de l'URL "
                  "pour le forum: '{}'.".format(forum))
            sleep(5)
NBKL
Niveau 10
24 juin 2017 à 23:50:34

Le 24 juin 2017 à 23:45:16 Blaff4 a écrit :
Nope, généralement il faut mieux minimiser le code dans un try afin d'avoir une gestion d'erreur plus fine et ainsi localiser plus précisément le problème.
En plus, si tu faisais ça et que le 18-25 était bugué alors les autres forums ne seraient jamais testés bien qu'ils puissent peut-être être accessibles, eux.

Personnellement, je regrouperai mes forums dans une liste et j'itérerai en boucle à travers afin de pouvoir tester un par un chacun d'eux. :ok:

forums = [dixhuit_vingtcinq, moins_quinze, quinze_dixhuit, overwatch]

while True:
    for forum in forums:
        try:
            forum.add_to_database()
        except URLError:
            print("Une erreur est survenue lors de l'ouverture de l'URL "
                  "pour le forum: '{}'.".format(forum))
            sleep(5)

Ah ouai d'accord, c'est exactement ce qu'il me faudrait. J'espère que ca viendra avec le temps cette gestion des choses. Merci en tout cas [[sticker:p/1kkr]]

Caecilius
Niveau 12
25 juin 2017 à 18:41:51

faire ce genre de programme sans requests :mort:

NBKL
Niveau 10
25 juin 2017 à 19:57:58

Le 25 juin 2017 à 18:41:51 Caecilius a écrit :
faire ce genre de programme sans requests :mort:

Ca fonctionnait très bien pour ce que je souhaitais faire :noel:

NBKL
Niveau 10
25 juin 2017 à 20:24:53

D'ailleurs, j'ai un souci. Depuis que je suis passé à requests j'ai un souci :(

Mon code

  def recup_co(self):
                r = requests.get(self.url_forum)
                page_html = str(r.text) # stockage du contenu de la page dans une variable
                page = BeautifulSoup(page_html, 'html.parser')
                resultat = page.select(".nb-connect-fofo")

                temp = str(resultat) #stockage de la ligne avec le nombre de co

                nb_co = re.search(self.pattern, temp)

                return nb_co[0]

Et j'ai l'erreur :

File "parser.py", line 59, in <module>
    main()
  File "parser.py", line 54, in main
    forum.add_to_database()
  File "parser.py", line 26, in add_to_database
    text = "INSERT INTO {0}(datetime, nb_co) VALUES('{1}', '{2}')".format(self.forum, now, self.recup_co())
  File "parser.py", line 43, in recup_co
    return nb_co[0]
TypeError: '_sre.SRE_Match' object is not subscriptable

Je précise que j'ai cette erreur seulement sur mon serveur Debian, sur Windows ca marche niquel chrome :(

Merci d'avance

Blaff4
Niveau 10
25 juin 2017 à 21:50:50

Ça n'a rien à voir avec Windows ou Debian. :non:

Regarde comment s'utilise re.search() : https://docs.python.org/3rg/3/library/re.html#re.search :ok:

C'est une fonction qui retourne soit un "match object" ( https://docs.python.org/3/library/re.html#match-objects ), soit None si rien n'est trouvé.

Pour récupérer la valeur contenue dans ton objet, tu dois utiliser nb_co.group(0) à la place de nb_co[0]. :-)))

Par contre, si tu remarques un comportement différent entre Windows et Debian c'est que tu as peut-être un problème ailleurs.

NBKL
Niveau 10
25 juin 2017 à 21:54:14

Le 25 juin 2017 à 21:50:50 Blaff4 a écrit :
Ça n'a rien à voir avec Windows ou Debian. :non:

Regarde comment s'utilise re.search() : https://docs.python.org/3rg/3/library/re.html#re.search :ok:

C'est une fonction qui retourne soit un "match object" ( https://docs.python.org/3/library/re.html#match-objects ), soit None si rien n'est trouvé.

Pour récupérer la valeur contenue dans ton objet, tu dois utiliser nb_co.group(0) à la place de nb_co[0]. :-)))

Par contre, si tu remarques un comportement différent entre Windows et Debian c'est que tu as peut-être un problème ailleurs.

Ah d'accord, ca marche bien maintenant, mais je trouve ça bizarre que ca fonctionne très bien avec Windows :(

Merci en tout cas :-)

1
Sujet : [Python] Implémenter gestion d'erreur
   Retour haut de page
Consulter la version web de cette page