Python 3 Multi-Threading with Tkinter - python

I have been writing a bit of code that will eventually take commands from a remote and local (within the code itself) source and and then will be carried out and the results displayed using tkinter.
The Problem I am currently having is that when I run the code using threading and queues this error appears and I have tried putting the gui code at the bottom under the for loops for the threading but this had another error that occurred.
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 60, in threader
t_visuals()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 49, in t_visuals
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
File "C:\Python34\lib\tkinter\__init__.py", line 2604, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 2122, in __init__
(widgetName, self._w) + extra + self._options(cnf))
RuntimeError: main thread is not in main loop
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 58, in threader
t_connections()
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 43, in t_connections
sLog_update("waiting for connection...")
File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 40, in sLog_update
v.set(g)
File "C:\Python34\lib\tkinter\__init__.py", line 263, in set
return self._tk.globalsetvar(self._name, value)
RuntimeError: main thread is not in main loop
This is the code:
from socket import *
import time
from tkinter import *
import threading
from queue import Queue
#server setup
HOST = ''
PORT = 24601
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
#Window Setup
HEIGHT = 720
WIDTH = 1280
root = Tk()
root.title("Server Controler")
root.geometry("1280x720")
#Variables needed
v =StringVar()
f =StringVar()
g = "" #Server update log
#locked variables
sLog_lock = threading.Lock()
#t_ means threaded
def sLog_update(self):
with sLog_lock:
global g
currentTime = str("["+time.ctime()+"] ")
g+=str(currentTime)
g+=str(self)
g+=str("\n")
v.set(g)
def t_connections():
sLog_update("waiting for connection...")
tcpCliSock, addr = tcpSerSock.accept()
avr = "connected from: " + str(addr)
sLog_update(avr)
def t_visuals():
label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
entry = Entry(root, width=105,relief=RIDGE,bd=5,textvariable=f).grid(row=2,column=0)
button = Button(root,command= lambda:sLog_update(f.get()),text="send").grid(row=3,column=0)
mainloop()
def threader():
worker = q.get()
print(worker)
if worker == 1:
t_connections()
elif worker == 0:
t_visuals()
q =Queue()
for x in range(2):
t = threading.Thread(target=threader)
t.daemon = True
t.start()
for worker in range(20):
q.put(worker)
q.join()

You can make this problem going away by keeping all of the GUI code in the main thread.

Related

python socket & Tkinter: Starting tkinter class not working in a python socket program

Hello I'm trying to do an online python game with socket and tkinter. Here are my 2 files: server.py and client.py.
Don't worry of the lots of code, there is an explanation at the end ;)
server.py:
import socket
import multiprocessing
from tkinter import *
import pickle
def foo(l):
return list(map(int, l))
IP = #<my_IPv4>
PORT = 1234
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((IP, PORT))
msg = "[800, 400]"
s.listen(1)
conn, addr = s.accept()
receivedPos = []
changePosCount = 0
print("Line 22")
def ReceivePosition():
while True:
receivedPos = pickle.loads(conn.recv(20))
if not receivedPos:
break
else:
changePosCount = changePosCount +1
print("Line 30")
changingPos = multiprocessing.Process(target=ReceivePosition)
changingPos.start()
print("Line 33")
while changePosCount == 0:
continue
class root(Tk):
def __init__(self):
super(root, self).__init__()
self.title("1- Tkinter Changing Position")
self.minsize(500,400)
print("Line 43")
self.createLabel()
print("Line 45")
def createLabel(self):
self.label = Label(self, text = str(receivedPos).replace('[', '').replace(']', '') , bg='black', fg='blue', font='Calibri 40 bold')
print("Line 48")
self.label.place(x=receivedPos[0], y=receivedPos[1])
print("Line52")
root = root()
root.mainloop()
print("Line 55")
client.py:
import socket
import pickle
def foo(l):
return list(map(int, l))
IP = #<my_IPv4>
PORT = 1234
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP, PORT))
while True:
enteredPos = foo(str(input("New Position (Separate x and y with a \",\", eg: 40,60): ")).split(','))
enteredPos_bytes = pickle.dumps(enteredPos)
s.sendall(enteredPos_bytes)
print(f"You placed the label at x={enteredPos[0]}, y={enteredPos[1]}")
Explanation:
At first, I have 2 empty variables: receivedPos and changePosCount: so the function ReceivePosition will receive the position given by the client and assign it to receivedPos and will then add 1 to changePosCount. This function will to run in parallel to the rest of the program, but only after that the client enter a position.
Now that the client has entered a position that has been assigned to receivedPos, and that changePosCount is greater than 0, we have 2 pieces of code that are running in parallel: the ReceivePosition function and the code that set up the tkinter GUI.
As you can see I've made so that so that every few lines of code it prints which line is executed, and I deduced that the program is returning the error when it should create the GUI (at line 36). Here's the error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\multiprocessing\spawn.py", line 125, in _main
prepare(preparation_data)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\multiprocessing\spawn.py", line 236, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\multiprocessing\spawn.py", line 287, in _fixup_main_from_path
main_content = runpy.run_path(main_path,
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 288, in run_path
return _run_module_code(code, init_globals, run_name,
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "d:\Users\Jean Paul\OneDrive\Programming\JP\Socket\Exercises\1- Tkinter Changing Position\server.py", line 13, in <module>
s.bind((IP, PORT))
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
I googled to see what this error means and apparently it shows up when the used port isn't available, but it gives me this error for any port, available or not.
Thank you for reading my question and for trying to help me.
You can accomplish this with threads. This is a very rough example from hacking on your code. Run the server, then the client, then type some coordinates. I dropped pickle since it isn't secure and you can just send the input text and parse it. I used socket.makefile and its .readline() method which will read up to a sent newline, so multiple messages can be sent if needed. TCP is a byte streaming protocol and only guarantees bytes sent are received in the same order, but you need to build a protocol on top of that to delimit messages for reliability.
client.py
import socket
HOST = 'localhost'
PORT = 1234
s = socket.socket()
s.connect((HOST, PORT))
while True:
enteredPos = input('New Position (Separate x and y with a comma, e.g.: 40,60): ')
s.sendall(enteredPos.encode() + b'\n')
x,y = enteredPos.split(',')
print(f'You placed the label at {x=}, {y=}')
server.py
import socket
import threading
from tkinter import *
HOST = ''
PORT = 1234
s = socket.socket()
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
receivedPos = ''
def receive(conn,addr):
with conn, conn.makefile('r',encoding='utf8') as reader:
while True:
global receivedPos
receivedPos = reader.readline()
print(receivedPos)
if not receivedPos:
break
x,y = [int(n) for n in receivedPos.split(',')]
root.label.config(text=receivedPos)
root.label.place(x=x, y=y)
class Root(Tk):
def __init__(self):
super().__init__()
self.title("1- Tkinter Changing Position")
self.minsize(500,400)
self.label = Label(self, text = receivedPos, bg='black', fg='blue', font='Calibri 40 bold')
root = Root()
threading.Thread(target=receive, args=(conn, addr), daemon=True).start()
root.mainloop()

RuntimeError: main thread is not in main loop when tkinter GUI is closed

I'm trying to create a tkinter GUI that presents the 10 processes that are taking up the cpu, refreshing it every 2 seconds, similar to top, on the linux command line. My code is:
import time
import threading
import logging
import psutil
from functools import cmp_to_key
from tkinter import *
import tkinter.scrolledtext as ScrolledText
class TextHandler(logging.Handler):
def __init__(self, text):
logging.Handler.__init__(self)
self.text = text
def emit(self, record):
msg = self.format(record)
def append():
self.text.configure(state='normal')
self.text.insert(END, msg + '\n')
self.text.configure(state='disabled')
# Autoscroll to the bottom
self.text.yview(END)
# This is necessary because we can't modify the Text from other threads
self.text.after(0, append)
class myGUI(Frame):
def __init__(self):
self.window = Tk()
self.window.title("TOP GUI")
self.window.configure(bg='#999999')
self.window.minsize(width=400, height=400)
self.window.resizable(0, 0)
self.lable_title = Label(self.window,
text=" Table of Processes ",
font=("Arial", 20, "bold"),
bg='#4F4F4F', fg='#E6BA00', highlightthickness=2)
self.lable_title.pack(pady=10)
self.frame_label1 = Label(self.window,
text='\n Below are listed the 10 processes with the highest \n'
+ 'CPU consumption, with 5 second refresh. \n',
bg='#E6BA00',
highlightthickness=0,
width=43,
borderwidth=2,
relief='ridge')
self.frame_label1.pack(pady=20)
self.frame_top_message = Frame(self.window, bg='#999999')
self.frame_botao_go = Frame(self.window, bg='#999999')
self.frame_top_message.pack(pady=20)
self.frame_botao_go.pack(pady=20)
self.button_completed = Button(self.frame_botao_go,
font='Arial 14 bold',
text='GO',
width=10,
command=self.window.destroy)
self.button_completed.pack(side='left', padx=50)
self.button_completed.configure(bg='#E6BA00')
# Add text widget to display logging info
st = ScrolledText.ScrolledText(self.frame_top_message)
st.configure(font='TkFixedFont',
width=50,
height=15)
st.pack(padx=30)
# Create textLogger
text_handler = TextHandler(st)
# Logging configuration
logging.basicConfig(filename='test.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# Add the handler to logger
logger = logging.getLogger()
logger.addHandler(text_handler)
trheading()
self.window.mainloop()
def trheading():
t2 = threading.Thread(target=worker, args=[])
t2.start()
def worker():
def cmpCpu(a, b):
a = a['cpu']
b = b['cpu']
if a > b:
return -1
elif a == b:
return 0
else:
return 1
while True:
timestamp = time.asctime()
logging.info(timestamp)
# Collect information for each process
processes = []
for proc in psutil.process_iter(attrs=['name', 'cpu_percent']):
processes.append({'name': proc.info['name'], 'cpu': proc.info['cpu_percent']})
# Sort by cpu usage
logging.info("CPU:")
processes.sort(key=cmp_to_key(cmpCpu))
for i in range(10):
info = processes[i]
info = info['name'] + ", " + str(info['cpu']) + "%"
logging.info(info)
logging.info("\n")
time.sleep(2)
t1 = threading.Thread(target=myGUI, args=[])
t1.start()
It will be used as a module of another larger program and will allow the user to follow a series of processes launched through subprocess.run.
It was written by putting together several examples from the internet. It works very well, but when I click the GO button I get the error message:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/home/arymaia/PycharmProjects/TopIso3D_Viewer_vbeta/Table_of_Processes_2.py", line 116, in worker
logging.info(timestamp)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 2097, in info
root.info(msg, *args, **kwargs)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1446, in info
self._log(INFO, msg, args, **kwargs)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1589, in _log
self.handle(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1599, in handle
self.callHandlers(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1661, in callHandlers
hdlr.handle(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 952, in handle
self.emit(record)
File "/home/arymaia/PycharmProjects/TopIso3D_Viewer_vbeta/Table_of_Processes_2.py", line 27, in emit
self.text.after(0, append)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/tkinter/__init__.py", line 821, in after
name = self._register(callit)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/tkinter/__init__.py", line 1528, in _register
self.tk.createcommand(name, f)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread
I researched several answers that explain that tkinter has limitations with the use of trheading, but what I found different was that the code I made works without error, until the moment of being closed.
Could someone explain to me why this is and how I can solve this problem?

Tkinter with multiprocessing: OSError [Errno 22] Invalid argument

I'm trying to add multiprocessing to my tkinter app and I've been having issues with the error: TypeError: cannot pickle '_tkinter.tkapp' object. I had a look at the solution proposed in the question here and tried to implement my own version of it and this appears to have solved this particular error but now I instead I have constant OSError: [Errno 22] Invalid argument:
What I aspire to have the code do is that some calculation is being performed in the background and results of this calculation are being put into the Queue (here just integers but will be Numpy arrays in the actual code). The GUI application then displays some statistics and results to the user.
from multiprocessing import Process, Queue
from queue import Empty
import tkinter as tk
from tkinter import Tk
class FooUI(Process):
def __init__(self, q: Queue):
super().__init__(target=self, args=(q,))
self.queue = q
self.duh = []
self.root = Tk()
self._create_interface()
self.root.after(100, self._check_queue)
self.root.mainloop()
def _check_queue(self):
try:
out = self.queue.get_nowait()
if out:
self.duh.append(out)
print(self.duh)
return
except Empty:
pass
self.root.after(100, self._check_queue)
def _create_interface(self):
self.root.geometry("100x100")
b = tk.Button(self.root, text='Start', command=self.calc)
b.grid(row=0, column=0)
def calc(self):
p = Process(target=do_calc)
p.start()
def do_calc(q: Queue):
for i in range(20):
q.put(i**2)
If __name__ == '__main__':
q = Queue()
f = FooUI(q)
f.start()
And here is the traceback:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 125, in _main
prepare(preparation_data)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 236, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 287, in _fixup_main_from_path
main_content = runpy.run_path(main_path,
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 264, in run_path
code, fname = _get_code_from_file(run_name, path_name)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 234, in _get_code_from_file
with io.open_code(decoded_path) as f:
OSError: [Errno 22] Invalid argument: 'C:\\python\\block_model_variable_imputer\\<input>'
Traceback (most recent call last):
File "<input>", line 3, in <module>
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\context.py", line 327, in _Popen
return Popen(process_obj)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_tkinter.tkapp' object
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 125, in _main
prepare(preparation_data)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 236, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\multiprocessing\spawn.py", line 287, in _fixup_main_from_path
main_content = runpy.run_path(main_path,
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 264, in run_path
code, fname = _get_code_from_file(run_name, path_name)
File "C:\Users\cherp2\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 234, in _get_code_from_file
with io.open_code(decoded_path) as f:
OSError: [Errno 22] Invalid argument: 'C:\\python\\block_model_variable_imputer\\<input>'
I've been trying for a while to get it to work. Any help will be greatly appreciated!
You do the subclass of Process() in a wrong way. You need to override the run() method instead of passing target option.
from multiprocessing import Process, Queue
from queue import Empty
import tkinter as tk
class FooUI(Process):
def __init__(self, q: Queue):
super().__init__() # don't pass target and args options
self.queue = q
self.duh = []
# override run() method and create the Tk() inside the function
def run(self):
self.root = tk.Tk()
self._create_interface()
self.root.after(100, self._check_queue)
self.root.mainloop()
def _check_queue(self):
try:
out = self.queue.get_nowait()
if out:
self.duh.append(out)
print(self.duh)
#return
except Empty:
pass
self.root.after(100, self._check_queue)
def _create_interface(self):
self.root.geometry("100x100")
b = tk.Button(self.root, text='Start', command=self.calc)
b.grid(row=0, column=0)
def calc(self):
if self.queue.empty():
self.duh.clear()
p = Process(target=do_calc, args=[self.queue]) # pass self.queue to do_calc()
p.start()
def do_calc(q: Queue):
for i in range(20):
q.put(i**2)
if __name__ == '__main__':
q = Queue()
f = FooUI(q)
f.start()

Python Multi threading - Rawlink error on connection.wait()

I am trying to multithread a Singal R connection with python, I am getting a connection Rawlink error the connections works and I need to wait 1 second in order to receive the message from the client, I am also using a barrier to execute the thread "simultaneous".
Here is my code
with Session() as session:
global connection
connection = Connection("http://sampleSINGALRURL/signalr", session)
presenceservice = connection.register_hub('ClientRegistration')
presenceservice1 = connection.register_hub('PresenceClientHub')
connection.start()
presenceservice.server.invoke('IdentifyClient', devideIdentity, softwareVersion, IpAddress,
machineName, DeviceType, patientAdmissionGuid, patientID, pairingId)
presenceservice1.client.on('StaffPresenceNotified', self.get_data1)
connection.wait(1)
And then my threading functions
def get_clients(self):
global barrier
self.connect_to_database1()
barrier.wait()
self.get_message_from_client1()
self.print_data1()
def send_messages(self):
global MessageNumber
global machineName
global staffName
global request
machineName = final_result[MessageNumber][0]
staffName = staff_results[MessageNumber][0]
MessageNumber += 1
barrier.wait()
request = requests.post(
"http://sampleurl/api/sample")
return request
def print_response(self):
global request
timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
logging.info("Message sent at " + "Time : " + timestamp + " " + machineName)
def Spin_Clients(self, NumMessages):
for i in range(10):
self.client_list.append(Thread(target=self.send_messages))
self.client_list[i].start()
self.print_response()
sleep(2)
for i in range(10):
self.Message_List.append(Thread(target=self.get_clients))
self.Message_List[i].start()
for thread in self.client_list:
thread.join()
for thread in self.Message_List:
thread.join()
Error logs
All threads have finished
11:41:37.243
Exception in thread Thread-13: Traceback (most recent call last): File "c:\users\appdata\local\programs\python\python37\lib\threading.py", line 917, in _bootstrap_inner
self.run()
File "c:\users\appdata\local\programs\python\python37\lib\threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "C:\Data\LoadTest.py", line 103, in get_clients
self.get_message_from_client1()
File "C:\Data\LoadTest.py", line 89, in get_message_from_client1
connection.wait(1)
File "c:\users\appdata\local\programs\python\python37\lib\site-packages\signalr\_connection.py", line 60, in wait
gevent.joinall([self.__greenlet], timeout)
File "src\gevent\greenlet.py", line 849, in gevent._greenlet.joinall
File "src\gevent\greenlet.py", line 859, in gevent._greenlet.joinall
File "src\gevent\_hub_primitives.py", line 198, in gevent.__hub_primitives.wait_on_objects File "src\gevent\_hub_primitives.py", line 235, in gevent.__hub_primitives.wait_on_objects
File "src\gevent\_hub_primitives.py", line 125, in gevent.__hub_primitives._WaitIterator.__iter__ AttributeError: 'NoneType' object has no attribute 'rawlink'
I also tried to use locks but that had the same outcome.
Any idea?

Threading a faker inside a flask app

I have a flask app with websockets, and when a person hits a socket to start threading, I want it to run a thread like:
#socketio.on('start', namespace='/ws')
def patrol():
asset = {'x': 0, 'y': 1}
while True:
thread_patrol(asset, [[0, 0], [400, 400]])
def patrol(asset, coordinates):
count = 0
import itertools
for coordinate in itertools.cycle(coordinates):
val = True
while val:
asset, val = take_step(asset, coordinate[0], coordinate[1])
emit('asset',
{'data': asset, 'count': count},
broadcast=True)
count += 1
time.sleep(1)
import threading
def thread_patrol(asset, coordinates):
print('threading!')
patrolling_thread = threading.Thread(target=patrol, args=(asset, coordinates))
patrolling_thread.start()
def take_step(asset, x, y):
asset[x] = x
asset[y] = y
But then I get an error because it's outside of request context. What do I need to do to allow my app to thread?:
threading!
Exception in thread Thread-2005:
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "app2.py", line 270, in patrol
broadcast=True)
File "/usr/local/lib/python2.7/site-packages/flask_socketio/__init__.py", line 520, in emit
namespace = flask.request.namespace
File "/usr/local/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/local/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
return self.__local()
File "/usr/local/lib/python2.7/site-packages/flask/globals.py", line 20, in _lookup_req_object
raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context
You (I) have to include thread.daemon = True to inform the app to run it as a background process, and I removed broadcast=True since that wasn't necessary anyways.
def thread_patrol(asset, coordinates):
patrolling_thread = Thread(target=patrol, args=(asset, coordinates))
thread.daemon = True
thread.start()

Categories