Reputation: 533
I am trying to create a console in a GUI, pyqt5, and I am having trouble getting the output from the InteractiveInterpreter. I do not know if my InteractiveInterpreter is threaded properly or what. when I run the code below (without trying to capture the output ) the code is printed sequentially but I would expect to have an output to be something like this:
hi
0 interpreter
0 main
1 interpreter
1 main
2 interpreter
2 main
3 interpreter
4 interpreter
instead I get this:
hi
0 interpreter
1 interpreter
2 interpreter
3 interpreter
4 interpreter
0 main
1 main
2 main
code:
import code
import threading
from time import sleep
import sys
class IC(threading.Thread):
def __init__(self, context=None):
threading.Thread.__init__(self)
self.Console = code.InteractiveInterpreter(context)
def push(self, x, sym=''):
return self.Console.runsource(x,sym)
if __name__ == "__main__":
a=IC()
a.start()
a.push("print('hi')")
a.push("from time import sleep")
a.push("for i in range(5):\n\t print(i,'interpreter')\n\t sleep(1)\n")
for i in range(3):
print(i, 'main')
sleep(1)
Update: I the code is now running like I expect however I am unable to catch print statements. I tried using contxtlib but I am getting the text as it is printing, but in one large chunck. How can I capture the print statements as they come, latter I will pass these strings to a qtextedit.
this is the code as I'm using now:
import code
import threading, queue
from time import sleep
import sys
import io
from contextlib import redirect_stdout
class IC:
def __init__(self):
self.On = True
self.qin = queue.Queue()
self.qout = queue.Queue()
self.thread = threading.Thread(target=self.runtime, daemon=True).start()
def push(self, x):
self.qin.put(x)
def runtime(self):
self.Console = code.InteractiveInterpreter()
while self.On:
f = io.StringIO()
with redirect_stdout(f):
if self.qin.qsize()>0:
self.Console.runsource(self.qin.get())
if f.getvalue():
print("caught:", f.getvalue())
if __name__ == "__main__":
a=IC()
a.push("print('hi')")
a.push("from time import sleep")
a.push("for i in range(5):\n\t print(i,'interpreter')\n\t sleep(2)\n")
for i in range(3):
print(i, 'main')
sleep(1.5)
and this is the output I'm getting, in idle. The first two lines are what I want/expect, but when I enter the for loop I have to wait for it to get out for me to get the results, instead of getting each print statement individually.
caught: 0 main
caught: hi
>>> caught: 0 interpreter
1 main
1 interpreter
2 main
2 interpreter
3 interpreter
4 interpreter
Upvotes: 0
Views: 258
Reputation: 1657
@user2357112supportsMonica is correct. You create a thread and then start the thread but the thread isn't doing anything. The interactive interpreter was initialized in the thread class and you added a function to the thread class but all the calls you do are from the main thread and run on the main thread.
The only time code is run inside the thread you created is when the code is in the target function.
I would suggest you review threading in the python documentation and specifically look at how to set the target of a thread and how to loop in the thread to keep it alive and working. Then also you may need to look into Queues
for passing data to the new thread.
Upvotes: 0