I'm having some issues when running my code inside Spyder3 IPython console. Now I did some digging on this and come to the conclusion that either I have graphical issues regarding drivers or X11 forwarding or whatsoever.
Or I simply have an issue of not properly cleaning up my code which is why the second execution always becomes troublesome, requiring a kernel restart which as well might cause errors due to BadWindows etc.
I do hope cleaning up properly will suffice, because dealing with any of these XCB errors or GTK warnings is too complicated
My question is: How do I properly cleanup tkinter window objects, pygame surfaces and multithreads? Expectation: Delete everything after the window is closed because it certainly is not required anymore at that point or will simply cause errors if it persists.
I've read about the python Deconstructor del but before I go into this I would prefer to know what kind of things even require deletion.
Here's an example of error message I get on second execution of my program (first execution works properly)
An error ocurred while starting the kernel
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi‑threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: ../../src/xcb_io.c:259: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 2 (X_ChangeWindowAttributes)
Resource id in failed request: 0xe00008
Serial number of failed request: 75
Current serial number in output stream: 76
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 2 (X_ChangeWindowAttributes)
Resource id in failed request: 0xe00008
Serial number of failed request: 75
Current serial number in output stream: 76
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 2 (X_ChangeWindowAttributes)
Resource id in failed request: 0xe00008
Serial number of failed request: 75
Current serial number in output stream: 76
And here is the Code that I'm testing:
import pygame as pg
import pygame.camera
import os
import threading as th
class Capture():
def __init__(self, parent):
os.environ['SDL_WINDOWID'] = parent
pg.display.init()
pg.camera.init()
self.size = (640,480)
self.display = pg.display.set_mode(self.size)
self.display.fill(pg.Color(255,255,255))
pg.display.update()
self.clist = pg.camera.list_cameras()
if not self.clist:
raise ValueError('Sorry, no cameras detected.')
print('Cameras: ', self.clist)
self.snapshot = pg.surface.Surface(self.size, 0, self.display)
def feed(self, number):
try:
self.cam = pg.camera.Camera(self.clist[number], self.size)
except IndexError:
print('Provided Camera not available.')
self.cam.start()
self.thread = True
self.t = th.Thread(name='Livefeed', target=self.live)
self.t.start()
def live(self):
while self.thread:
if self.cam.query_image():
self.cam.get_image(self.snapshot)
self.display.blit(self.snapshot, self.snapshot.get_rect())
pg.display.update()
def stop(self):
self.thread = False
self.t.join()
self.cam.stop()
#for Camera DEBUG
if __name__ == '__main__':
import tkinter as tk
root = tk.Tk()
embed = tk.LabelFrame(root, width=650, height=490)
embed.grid(row=0, column=0)
root.update()
setup = Capture(str(embed.winfo_id()))
buttons = tk.LabelFrame(root, width=100)
buttons.grid(row=0, column=1)
cam1 = tk.Button(buttons, text='Cam 1',
command=lambda: setup.feed(0), width=25)
cam2 = tk.Button(buttons, text='Cam 2',
command=lambda: setup.feed(1), width=25)
cam3 = tk.Button(buttons, text='Cam 3',
command=lambda: setup.feed(2), width=25)
cam4 = tk.Button(buttons, text='Cam 4',
command=lambda: setup.feed(3), width=25)
cam1.grid(row=0, columnspan=2)
cam2.grid(row=1, columnspan=2)
cam3.grid(row=2, columnspan=2)
cam4.grid(row=3, columnspan=2)
camStop = tk.Button(buttons, width=50, text='Feed Off',
command=lambda: setup.stop())
camStop.grid(row=4, columnspan=2)
root.mainloop()