I want to print my stdout to GUI in python. I am using Tkinter. This is what I is working for me
def get_likes_button():
output = subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE)
s1 = output.stdout.read()
text.delete("1.0",END)
text.insert(INSERT,s1)
But, I am getting the whole output at once. What I want is that the GUI should print the output iteratively just like it prints on terminal.
So, I tried this, but it gave me an error on clicking the button
def get_likes_button():
text.delete("1.0",END)
with subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE) as output:
s1 = output.stdout.read()
text.insert(INSERT,s1)
The error is
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__
return self.func(*args)
File "gui.py", line 88, in get_likes_button
with subprocess.Popen(['python', "getLikes.py"], stdout=subprocess.PIPE) as output:
AttributeError: __exit__
Can you please suggest me what to do?
Popen
does not support context managers (ie with
) hence the error. But also note that there is no practical difference between the 2 versions of your code.
You could instead read line by line:
def get_likes_button():
child = subprocess.Popen(['python', 'getLikes.py'], stdout=subprocess.PIPE)
text.delete("1.0",END)
for line in iter(child.stdout.readline, ''):
text.insert(INSERT, line)
child.stdout.close()
child.wait()
The line for line in iter(child.stdout.readline, ''):
is used to work around the buffering that would be experienced if the loop had been for line in child.stdout:
.
Update
Try revising the code as follows:
def get_likes_button():
child = subprocess.Popen(['python', '-u', 'getLikes.py'], stdout=subprocess.PIPE)
text.delete("1.0",END)
for line in iter(child.stdout.readline, ''):
text.insert(INSERT, line)
text.see(END)
text.update_idletasks()
child.stdout.close()
child.wait()
The changes are:
-u
python option for unbuffered output in the child, text.see(END)
to scroll the text window to the bottom after each insert, text.update_idletasks()
to give Tkinter a chance to update the text widget. This might help to avoid using threads, but the one down side of this is that the rest of the GUI will be unresponsive while your callback is executing. That might be acceptable if your child process is short lived, perhaps not if the child runs for an extended period - it depends on your application.
I don't think subprocess.Popen
can be used within with
clause. I think check_output
is what you need:
output = subprocess.check_output(['python', 'getLikes.py'])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.