Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #35264 > unrolled thread

Keeping a Tkinter GUI alive during a long running process

Started byKevin Walzer <kw@codebykevin.com>
First post2012-12-20 22:04 -0500
Last post2012-12-29 18:47 +0000
Articles 3 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Keeping a Tkinter GUI alive during a long running process Kevin Walzer <kw@codebykevin.com> - 2012-12-20 22:04 -0500
    Re: Keeping a Tkinter GUI alive during a long running process "Russell E. Owen" <rowen@uw.edu> - 2012-12-26 12:46 -0800
    Re: Keeping a Tkinter GUI alive during a long running process Grant Edwards <invalid@invalid.invalid> - 2012-12-29 18:47 +0000

#35264 — Keeping a Tkinter GUI alive during a long running process

FromKevin Walzer <kw@codebykevin.com>
Date2012-12-20 22:04 -0500
SubjectKeeping a Tkinter GUI alive during a long running process
Message-ID<kb0jjh$7pm$1@dont-email.me>
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

[toc] | [next] | [standalone]


#35541

From"Russell E. Owen" <rowen@uw.edu>
Date2012-12-26 12:46 -0800
Message-ID<mailman.1297.1356554827.29569.python-list@python.org>
In reply to#35264
In article <kb0jjh$7pm$1@dont-email.me>,
 Kevin Walzer <kw@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.
> 
> 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)

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

[toc] | [prev] | [next] | [standalone]


#35763

FromGrant Edwards <invalid@invalid.invalid>
Date2012-12-29 18:47 +0000
Message-ID<kbndsb$f1k$1@reader1.panix.com>
In reply to#35264
On 2012-12-21, Kevin Walzer <kw@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            

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web