Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Keeping a Tkinter GUI alive during a long running process

99 views
Skip to first unread message

Kevin Walzer

unread,
Dec 20, 2012, 10:04:18 PM12/20/12
to
I maintain a Tkinter application that's a front-end to to a package
manger, and I have never been able to find a way to keep the app from
locking up at some point during the piping in of the package manager's
build output into a text widget. At some point the buffer is overwhelmed
and the app simply can't respond anymore, or writes data to the text
widget after locking up for a period.

I've long used the typical Tkinter design pattern of opening a pipe to
the external command, and letting it do its thing. However, after a
time, this locks up the app. If I try to throttle the buffer with some
combination of "update" or "after" or "update_idletasks," that keeps the
data flowing, but it comes in too slowly and keeps flowing in long after
the external process has terminated.

Below is a sample function that illustrates how I approach this issue.
Can someone suggest a better approach?

#install a fink package
def installPackage(self):

self.package = self.infotable.getcurselection()
if not self.package:
showwarning(title='Error', message='Error', detail='Please
select a package name.', parent=self)
return
else:
self.clearData()
self.packagename = self.package[0][1]
self.status.set('Installing %s' % self.packagename)
self.setIcon(self.phynchronicity_install)
self.playSound('connect')
self.showProgress()
self.file = Popen('echo %s | sudo -S %s -y install %s' %
(self.passtext, self.finkpath.get(), self.packagename), shell=True,
bufsize=0, stdout=PIPE).stdout
for line in self.file:
self.inserturltext(line)
self.after(5000, self.update_idletasks)

--
Kevin Walzer
Code by Kevin
http://www.codebykevin.com

Russell E. Owen

unread,
Dec 26, 2012, 3:46:53 PM12/26/12
to pytho...@python.org
In article <kb0jjh$7pm$1...@dont-email.me>,
I suggest you use the threading or multiprocessing module: call
subprocess.Popen in the spawned thread or process, read stdout in a
tight loop write the result into a queue. Then have your main process
asynchronously read the queue using polling.

It sounds a bit complicated, but in lieu of a way to asynchronously read
the stdout pipe, I don't know what else to do that's safe.

Another option to consider is to use Twisted framework, which has its
own support for running tasks. However, if you are not using Twisted
already, it's a big addition.

-- Russell

Grant Edwards

unread,
Dec 29, 2012, 1:47:39 PM12/29/12
to
On 2012-12-21, Kevin Walzer <k...@codebykevin.com> wrote:

> I maintain a Tkinter application that's a front-end to to a package
> manger, and I have never been able to find a way to keep the app from
> locking up at some point during the piping in of the package manager's
> build output into a text widget. At some point the buffer is overwhelmed
> and the app simply can't respond anymore, or writes data to the text
> widget after locking up for a period.
>
> I've long used the typical Tkinter design pattern of opening a pipe to
> the external command, and letting it do its thing. However, after a
> time, this locks up the app. If I try to throttle the buffer with some
> combination of "update" or "after" or "update_idletasks," that keeps the
> data flowing, but it comes in too slowly and keeps flowing in long after
> the external process has terminated.

Isn't there a way in Tkinter to have a file descriptor produce an
event whenever it becomes readble?

http://stackoverflow.com/questions/3348757/how-to-make-tkinter-repond-events-while-waiting-socket-data

--
Grant Edwards grant.b.edwards Yow! ... he dominates the
at DECADENT SUBWAY SCENE.
gmail.com
0 new messages