Runtimeerror: Main Thread Is Not in Main Loop

Matplotlib and :RuntimeError: main thread is not in main loop:

matplotlib uses TkAgg for default. Backends like TkAgg, FltkAgg, GTK, GTKAgg, GTKCairo, Wx, and WxAgg are all GUI based. And most GUI backends require being run from the main thread. Thus, if you are running on an environment without GUI, it will throw RuntimeError: main thread is not in main loop.

Therefore, just switch to backends that do not use GUI: Agg, Cairo, PS, PDF, or SVG.

For example:

import matplotlib.pyplot as plt
plt.switch_backend('agg')

References: https://matplotlib.org/stable/faq/howto_faq.html#work-with-threads

Main thread is not in main loop

The reason you're still getting the RuntimeError even with the changes, is because you're is still trying to update the GUI from a thread — the one running the ping_func() method — that is not the same one running the tkinter GUI (which is a required because it doesn't support multithreading).

To fix that I have split ping_func() up into two separate parts, one the runs the ping command in another process and appends the results to the queue, and another that updates the GUI — the latter now being done in new method I added named process_incoming() (similar to the example to which I referred you).

Also note that the Demo2 class is no longer a subclass of Demo1 since there's no reason to do so (and it might confuse matters). I also changed the self.listBox attribute to self.treeview because that's what it is.

Although those changes alone would avoid the RuntimeError, in theory the GUI could still "freeze" until all the tasks completed because the pool.map() function blocks until all the tasks have completed, which could interfere with tkinter's mainloop() depending on how long that takes. To avoid that I changed pool.map() to pool.async() — which doesn't block because it's unnecessary given the Queue's contents are repeatedly polled.

import multiprocessing.dummy
import multiprocessing
import os
import socket
import sys
import subprocess
import re
import time
import threading
import tkinter.messagebox
from tkinter import ttk
import queue

class Demo1:
data = []
def __init__(self, master):
self.master = master
self.label=tkinter.Label(text="Add IP/Hostname")
self.label.pack()
self.t=tkinter.Text(self.master,height=20,width=50)
self.t.pack()
self.button = tkinter.Button(self.master,height=3,width=10, text="OK",
command=self.new_window)
self.button.pack()

def new_window(self):
self.inputValue = self.t.get("1.0",'end-1c')
Demo1.data = self.inputValue.split("\n")
self.master.destroy() # close the current window
self.master = tkinter.Tk() # create another Tk instance
self.app = Demo2(self.master) # create Demo2 window
self.master.configure(bg='#6EBFE4')
self.master.mainloop()

class Demo2:
t1 = []
s1 = True
display = []

def __init__(self, master):
self.master = master
self.kas(master)

def kas(self,master):
self.running = True
self.queue = queue.Queue()
Demo2.t1 = Demo1.data
self.master = master
cols = ('IP','Ping status')
self.treeview = ttk.Treeview(self.master, columns=cols)
for col in cols:
self.treeview.heading(col, text=col)
self.treeview.column(col,minwidth=0,width=170)
self.treeview.column('#0',width=50)
self.treeview.grid(row=1, column=0, columnspan=2)

num_threads = 5 * multiprocessing.cpu_count()
p = multiprocessing.dummy.Pool(num_threads)
p.map_async(self.ping_func, [x for x in Demo2.t1 if x])

self.periodic_call() # Start polling the queue for results.

def ping_func(self, ip):
pi = []
pingCmd = "ping -n 1 -w 1000 " + ip
with os.popen(pingCmd) as childStdout:
result = childStdout.readlines()
pi.append(ip)
if(any('Reply from' in i for i in result)
and any('Destination host unreachable' not in i for i in result)):
pi.append("success")
else:
pi.append("failed")
self.queue.put(pi) #Thread value to queue

def process_incoming(self):
""" Process any messages currently in the queue. """
while self.queue.qsize():
try:
msg = self.queue.get_nowait()
print(msg)
self.treeview.insert('', 'end', value=(msg)) # Update GUI.
except queue.Empty: # Shouldn't happen.
pass

def periodic_call(self):
self.master.after(200, self.periodic_call) # checking its contents periodically
self.process_incoming()
if not self.running:
import sys
sys.exit(1)

def main():
root = tkinter.Tk()
app = Demo1(root)
root.mainloop()

if __name__ == '__main__':
main()

(Python tkinter): RuntimeError: main thread is not in main loop

The reason is that u have used the Threading in the Tkinter loop which I guess we shouldn't.
Safe play is to use after. so Custom label can help us in this case

from tkinter import *
import threading, time
import sys
root = Tk()
class Custom(Label):
def __init__(self,parent,lst):
super().__init__(parent)
self['text']=lst[0]
self.marker=0
self.lst=lst[:]
self.note=len(lst)
self.after(250,self.change)
def change(self):
if self.marker>=self.note:self.marker=0
self['text']=self.lst[self.marker]
self.marker+=1
self.after(250,self.change)
loadings = ['loading', 'loading.', 'loading..', 'loading...']
loading_label = Custom(root,loadings)
loading_label.pack()
# destroy it whenever u want
root.mainloop()

console application main thread is not in main loop using pysimplegui

It looks like you cannot call PySimpleGUI/tkinter in another thread.
Here, try to set main program as one thread and called in PySimpleGUI/tkinter.
The same, remember that don't call PySimpleGUI directly in your main_program and use method window.write_event_value to generate an event, then do it in your event loop.

Example code,

from time import sleep
import threading
import PySimpleGUI as sg

def hello():
layout = [[sg.Text("Hello, my friend !")]]
window = sg.Window("Hello", layout, keep_on_top=True, modal=True)
window.read(timeout=1000, close=True)

def main_program():
count = 5
while count > 0:
window.write_event_value("Hello", None)
sleep(3)
count -=1
window.write_event_value(sg.WINDOW_CLOSED, None)

layout = [[]]

window = sg.Window("Title", layout, alpha_channel=0, finalize=True)
threading.Thread(target=main_program, daemon=True).start()
while True:

event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == "Hello":
hello()

window.close()


Related Topics



Leave a reply



Submit