IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Thread : main thread is not in mainloop()


Sujet :

Python

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2018
    Messages : 8
    Par défaut Thread : main thread is not in mainloop()
    Bonjour à tous,

    J'espère que tout va bien pour vous en ces temps de crise sanitaire.

    Pour un projet j'ai réalisé un programme en Python. Ce programme permet de scraper (avec bs4) un site de bourse et ensuite d'afficher les valeurs scrapées dans un graphique sur une fenêtre Tkinter. J'ai ajouté un thread pour pouvoir scraper les valeurs tout en continuant à mettre à jour le graphique.
    Le programme fonctionne correctement à première vue, mais au bout du deuxième ou troisième lancement il plante et affiche une erreur "main thread is not in mainloop()" puis "une erreur est survenue lors du démarrage du noyau" ou "Tcl_AsyncDelete: async handler deleted by the wrong thread".

    J'ai essayé de jouer sur les temps de boucle (after et time.sleep) et j'ai mis des join() pour être sûr que le thread se termine en fermeture du programme.
    J'ai effectué différentes recherches, mais je n'ai toujours pas trouvé solution à mon problème.

    Code :

    Fichier principale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
     
    #Librairies
    import tkinter as tk
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    import matplotlib
    matplotlib.use('Agg')
    import time
    import pandas as pd
    from threading import Thread
    from tkinter import messagebox
     
    #Importation du fichier scraping.py
    import scraping
     
    #variables
    global plot_counter
    plot_counter= 0
    global launch_scraping
    launch_scraping = False
    global df
     
    df = pd.DataFrame(columns = ['value', 'time', 'trend'])
     
    #Appelle une fois la fonction start_scraping  dans scraping.py
    def data_scraping():
        global df
        print("Scraping")
        df=scraping.start_scraping(df)
        df = df.sort_values('time')
        time.sleep(5)
     
    #Appelle data_scraping si launch scraping est True    
    def scrap_thread():
        global launch_scraping
        print("Thread beginning")
        while True:
            if launch_scraping:
                data_scraping()
            else:
                break
        print("Thread ending")
     
     
    # Si scrap_button est True launch scraping devient false et inversement
    #S'il est faux => lance le thread et la fonction refresh
    def click_scrap_button(event):
        global launch_scraping
        if launch_scraping:
            launch_scraping = False
            scrap_button_var.set("Launch scraping")
        else:
            scrap_button_var.set("Stop scraping")
            launch_scraping = True
            global thread_1
            thread_1=Thread(target=scrap_thread)
            thread_1.start()
            refresh()
     
     
    #refresh le graphique dans la fenêtre tkinter avec les nouvelles données scrapées      
     
    def refresh():
        global plot_counter
        global launch_scraping   
        if not launch_scraping:
            thread_1.join()
            print("No refreshing")
            return    plot_counter += 1
        print("Refreshing")        # deleting previous line
        ax.lines.pop(0)       
            # create a new line  
        ax.plot(df.time[:plot_counter], df.value[:plot_counter])
        canvas.draw()        
            #wait 5 s then call refresh again
        app.after(8000, refresh)
     
    #Permet de quitter l'application
    def quit_app():
        global launch_scraping
        launch_scraping = False
        thread_1.join()
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
            app.destroy() #Creating the scraping application
     
     
    #Initialisation de la fenêtre tkinter
     
    app = tk.Tk()
    frame_top = tk.Frame(app)
    frame_top.pack(side='top', fill="both")
    frame_title = tk.Frame(app)
    frame_title.pack(fill="both")
    title=tk.Label(frame_title, text="DAX price of share")
    title.pack()
    frame_center = tk.Frame(app)
    frame_center.pack(fill="both")
    frame_under_fig=tk.Frame(app)
    frame_under_fig.pack(fill="both")
    scrap_button_var= tk.StringVar()
    scrap_button=tk.Button(frame_under_fig, textvariable=scrap_button_var)
    scrap_button.pack()
    scrap_button_var.set("Launch scraping")   fig = Figure()
    canvas = FigureCanvasTkAgg(fig, frame_center)
    canvas.get_tk_widget().pack()  
    ax = fig.add_subplot(111)
    ax.plot([], [])
    app.bind("<ButtonRelease-1>", click_scrap_button) 
    app.protocol("WM_DELETE_WINDOW", quit_app)
    app.mainloop()

    fichier scraping.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    import pandas as pd
    from bs4 import BeautifulSoup
    from datetime import datetime,timedelta
    import requests
     
    #Scrap les valeurs de la bourse et les insère dans une dataframe
    def start_scraping(dataframe):
     
     
        info_scrap={}
     
        page = requests.get("https://www.boursorama.com/bourse/indices/cours/5pDAX/")
     
        soup = BeautifulSoup(page.text,'lxml')
     
        # we assign to "value" the last value of exchange rate we scraped
        value= soup.find("span",attrs={"class":"c-instrument c-instrument--last"}).text
        # this value is a string, we need to replace space by empty string before converting it into float
        value=value.replace(' ','')
        print(value)
        #we assign to trend the last value of the trend we scraped
        trend=soup.find("span",attrs={"class":"c-instrument c-instrument--variation"}).text
     
        current_time=datetime.now()
     
     
     
        # value is a string we convert it into float and then add it to the dictionnary info_scrap
        info_scrap["value"] = float(value)
        info_scrap["trend"]=trend
        info_scrap["time"]=current_time
     
        # each value of the dictionnary are appended to the dataframe
        dataframe=dataframe.append(info_scrap, ignore_index=True)
        # the function return the dataframe we put in parameter
        return dataframe

    Merci d'avance pour votre aide,
    Bonne journée,
    Webuzo

  2. #2
    Membre éprouvé
    Homme Profil pro
    Vagabong étudiant en annalyse du signal.
    Inscrit en
    Avril 2019
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Vagabong étudiant en annalyse du signal.
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2019
    Messages : 130
    Par défaut
    Bonjour,
    Bon déjà votre code ne semble pas syntaxiquement correct:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      File "test.py", line 68
        return    plot_counter += 1
                                ^
    SyntaxError: invalid syntax
    mais il y a aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      File "test.py", line 102
        scrap_button_var.set("Launch scraping")   fig = Figure()
                                                    ^
    SyntaxError: invalid syntax
    Même en résolvant ces 2 erreurs, j'ai encore un 'bs4.FeatureNotFound: Couldn't find a tree builder...' Bref, difficile de tester votre code!
    Ne mettez pas votre code exhaustif, simplifiez le au maximum pour qu'au moins il soit testable. Et mieux encore, si vous arrivez à le compacter suffisamment, d'autres personnes ayant le même problème auront plus de facilité à exploiter la réponse. Je vous le dis car il y a encore pas si longtemps, je faisais comme vous, jusqu’à ce qu'on me le dise aussi...

    J'ai déjà eu un problème similaire à celui que vous décrivez, je l'ai résolu en m'assurant que tous les threads soient tués AVANT de sortir du mainloop. Peut être tuez-vous la fenêtre tandis que d'autre thread sont encore en vie?

Discussions similaires

  1. RuntimeError: main thread is not in main loop
    Par bender86 dans le forum GTK+ avec Python
    Réponses: 0
    Dernier message: 30/07/2011, 12h21
  2. Réponses: 3
    Dernier message: 16/05/2009, 23h40
  3. [C#]Cross-thread operation not valid
    Par hrp dans le forum Windows Forms
    Réponses: 17
    Dernier message: 31/07/2007, 16h36
  4. Cross-thread operation not valid && serialport
    Par vince_lille dans le forum Windows Forms
    Réponses: 4
    Dernier message: 20/04/2007, 11h57
  5. multi thread or not
    Par ronki dans le forum Concurrence et multi-thread
    Réponses: 2
    Dernier message: 02/03/2007, 19h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo