Running a progress bar and a subprocess.call at the same time

Hello wxpython community,

I need to display a progress bar while a an R program is running in the background. I am not sure how to this. The following is what I have, but doing it this way, the timer doesn't start. I am guessing the subprocess.call should be placed somewhere else, but I am not sure where. As always, your help is very appreciated.

Thank you.

Here is the code:

import subprocess
import wx

class MyFrame(wx.Frame):
    def __init__(self,parent,id, title, tpval=""):
        wx.Frame.__init__(self,parent,id,title='An application',size=(900,750))
        
        self.SetBackgroundColour('tan')
        menuBar=wx.MenuBar()

        menu0=wx.Menu()
        menu0.Append(97, "&Open file","")
        menuBar.Append(menu0,"&File")
        
        self.Bind(wx.EVT_MENU,self.openfile,id=97)

    def openfile(self,event):

        dlgg=wx.FileDialog(self,"Choose a file",os.getcwd(),"","*.*",wx.OPEN)
        if dlgg.ShowModal() == wx.ID_OK:
        
            frame6=analysis(self,-1, "")
            frame6.Show(True)
dlgg.Destroy

class analysis(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,None,-1,title="Running analysis", size=(350,150))
       
panel55=wx.Panel(self,-1)

        self.count=0
        self.timer=wx.Timer(self,-1)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)
        
        self.gauge=wx.Gauge(panel55,-1,100,(20,50),(250,25))
        self.gauge.SetBezelFace(3)
        self.gauge.SetShadowWidth(3)
        self.timer.Start(100)

    def OnTimer(self,event):
# This is where the R process is called.
        command0='R CMD BATCH myRscript.R'
        subprocess.call(command0,shell=True)
        self.count=self.count+1
        self.gauge.SetValue(self.count)
        if self.count==100:
            self.timer.Stop()
            self.Close()
           
class MyApp(wx.App):
    def OnInit(self):
        myframe=MyFrame(None,-1,"commondialogs.py")
        myframe.Center
        myframe.Show(True)

app=MyApp(0)
app.MainLoop()

You're calling the sub-process every tick, and also waiting for it to complete. You want to (a) call it in the __init__ code (b) call it so it starts the process and returns immediately. Look at Popen and poll().
Probably
     self.proc = subprocess.Popen((["/bin/mycmd", "myarg"])
and in the timer loop:
     self.proc.poll()

I'm not an expert - you may need to tweak this. Phil

···

At 09:56 AM 3/6/2009, you wrote:

Hello wxpython community,

I need to display a progress bar while a an R program is running in the background. I am not sure how to this. The following is what I have, but doing it this way, the timer doesn't start. I am guessing the subprocess.call should be placed somewhere else, but I am not sure where. As always, your help is very appreciated.

Thank you.

Here is the code:

import subprocess
import wx

class MyFrame(wx.Frame):
    def __init__(self,parent,id, title, tpval=""):
        wx.Frame.__init__(self,parent,id,title='An application',size=(900,750))

        self.SetBackgroundColour('tan')
        menuBar=wx.MenuBar()

        menu0=wx.Menu()
        menu0.Append(97, "&Open file","")
        menuBar.Append(menu0,"&File")

        self.Bind(wx.EVT_MENU,self.openfile,id=97)

    def openfile(self,event):

        dlgg=wx.FileDialog(self,"Choose a file",os.getcwd(),"","*.*",wx.OPEN)
        if dlgg.ShowModal() == wx.ID_OK:

            frame6=analysis(self,-1, "")
            frame6.Show(True)
dlgg.Destroy

class analysis(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,None,-1,title="Running analysis", size=(350,150))

panel55=wx.Panel(self,-1)

        self.count=0
        self.timer=wx.Timer(self,-1)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)

        self.gauge=wx.Gauge(panel55,-1,100,(20,50),(250,25))
        self.gauge.SetBezelFace(3)
        self.gauge.SetShadowWidth(3)
        self.timer.Start(100)

    def OnTimer(self,event):
# This is where the R process is called.
        command0='R CMD BATCH myRscript.R'
        subprocess.call(command0,shell=True)
        self.count=self.count+1
        self.gauge.SetValue(self.count)
        if self.count==100:
            self.timer.Stop()
            self.Close()

class MyApp(wx.App):
    def OnInit(self):
        myframe=MyFrame(None,-1,"commondialogs.py")
        myframe.Center
        myframe.Show(True)

app=MyApp(0)
app.MainLoop()

Judith Flores wrote:

Hello wxpython community,

I need to display a progress bar while a an R program is running in the background. I am not sure how to this. The following is what I have, but doing it this way, the timer doesn't start. I am guessing the subprocess.call should be placed somewhere else, but I am not sure where. As always, your help is very appreciated.

Thank you.

Here is the code:

import subprocess
import wx

class MyFrame(wx.Frame):
    def __init__(self,parent,id, title, tpval=""):
        wx.Frame.__init__(self,parent,id,title='An application',size=(900,750))
                self.SetBackgroundColour('tan')
        menuBar=wx.MenuBar()

        menu0=wx.Menu()
        menu0.Append(97, "&Open file","")
        menuBar.Append(menu0,"&File")
                self.Bind(wx.EVT_MENU,self.openfile,id=97)
     def openfile(self,event):

        dlgg=wx.FileDialog(self,"Choose a file",os.getcwd(),"","*.*",wx.OPEN)
        if dlgg.ShowModal() == wx.ID_OK:
                    frame6=analysis(self,-1, "")
            frame6.Show(True) dlgg.Destroy

class analysis(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,None,-1,title="Running analysis", size=(350,150))
       panel55=wx.Panel(self,-1)

        self.count=0
        self.timer=wx.Timer(self,-1)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)
                self.gauge=wx.Gauge(panel55,-1,100,(20,50),(250,25))
        self.gauge.SetBezelFace(3)
        self.gauge.SetShadowWidth(3)
        self.timer.Start(100)

    def OnTimer(self,event):
# This is where the R process is called.
        command0='R CMD BATCH myRscript.R'
        subprocess.call(command0,shell=True)
        self.count=self.count+1
        self.gauge.SetValue(self.count)
        if self.count==100:
            self.timer.Stop()
            self.Close()
           class MyApp(wx.App):
    def OnInit(self):
        myframe=MyFrame(None,-1,"commondialogs.py")
        myframe.Center
        myframe.Show(True)

app=MyApp(0)
app.MainLoop()

      _______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

I had to solve a similar problem a month or so back. Do you want to block user input to the window while your program is running? Here's what I did, it's using a wx.dialog so it may different in how you would implement it, but it should give you an idea:

In the main application:
          # called when wx process finishes
    self.Bind(wx.EVT_END_PROCESS, self.on_end_process)

    def convert_dialog(self, cmd):
        """
        Called when the convert process begins, executes the process call and
        shows the convert dialog. cmd is a string representing the system
       call.
        """
        self.process = wx.Process(self)
        wx.Execute(cmd, wx.EXEC_ASYNC, self.process)

        self.dlg = ConvertProgress(self)
        self.dlg.ShowModal()

    def on_end_process(self, event):
        """
        Destroy the progress Gauge/process after the convert process returns
        """
        self.process.Destroy()
        self.dlg.Destroy()
        del self.dlg
        del self.process

class ConvertProgress(wx.Dialog):
    """
    Shows a Progres Gauge while file conversion is taking place.
    """

    def __init__(self, parent):
        """
        Defines a gauge and a timer which updates the gauge.
        """
        wx.Dialog.__init__(self, parent, title="Converting...", size=(250, 100))
        self.count = 0

        self.timer = wx.Timer(self)
        self.gauge = wx.Gauge(self, range=100, size=(180, 30))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.gauge, 0, wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.SetFocus()

        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        self.timer.Start(20)

    def on_timer(self, event):
        """
        Increases the gauge's progress.
        """
        self.count += 1
        self.gauge.SetValue(self.count)
        if self.count == 100:
            self.count = 0

Hopefully that should give you an idea of what to do :slight_smile:

Thank you Steven, I will try to implement it.

···

----- Original Message ----
From: Steven Sproat <sproaty@gmail.com>
To: wxpython-users@lists.wxwidgets.org
Sent: Friday, March 6, 2009 10:29:46 AM
Subject: Re: [wxpython-users] Running a progress bar and a subprocess.call at the same time

Judith Flores wrote:

Hello wxpython community,

I need to display a progress bar while a an R program is running in the background. I am not sure how to this. The following is what I have, but doing it this way, the timer doesn't start. I am guessing the subprocess.call should be placed somewhere else, but I am not sure where. As always, your help is very appreciated.

Thank you.

Here is the code:

import subprocess
import wx

class MyFrame(wx.Frame):
    def __init__(self,parent,id, title, tpval=""):
        wx.Frame.__init__(self,parent,id,title='An application',size=(900,750))
                self.SetBackgroundColour('tan')
        menuBar=wx.MenuBar()

        menu0=wx.Menu()
        menu0.Append(97, "&Open file","")
        menuBar.Append(menu0,"&File")
                self.Bind(wx.EVT_MENU,self.openfile,id=97)
     def openfile(self,event):

        dlgg=wx.FileDialog(self,"Choose a file",os.getcwd(),"","*.*",wx.OPEN)
        if dlgg.ShowModal() == wx.ID_OK:
                    frame6=analysis(self,-1, "")
            frame6.Show(True) dlgg.Destroy
class analysis(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,None,-1,title="Running analysis", size=(350,150))
       panel55=wx.Panel(self,-1)

        self.count=0
        self.timer=wx.Timer(self,-1)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)
                self.gauge=wx.Gauge(panel55,-1,100,(20,50),(250,25))
        self.gauge.SetBezelFace(3)
        self.gauge.SetShadowWidth(3)
        self.timer.Start(100)

    def OnTimer(self,event):
# This is where the R process is called.
        command0='R CMD BATCH myRscript.R'
        subprocess.call(command0,shell=True)
        self.count=self.count+1
        self.gauge.SetValue(self.count)
        if self.count==100:
            self.timer.Stop()
            self.Close()
           class MyApp(wx.App):
    def OnInit(self):
        myframe=MyFrame(None,-1,"commondialogs.py")
        myframe.Center
        myframe.Show(True)

app=MyApp(0)
app.MainLoop()

      _______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

I had to solve a similar problem a month or so back. Do you want to block user input to the window while your program is running? Here's what I did, it's using a wx.dialog so it may different in how you would implement it, but it should give you an idea:

In the main application:
        # called when wx process finishes
   self.Bind(wx.EVT_END_PROCESS, self.on_end_process)

   def convert_dialog(self, cmd):
       """
       Called when the convert process begins, executes the process call and
       shows the convert dialog. cmd is a string representing the system
      call.
       """
       self.process = wx.Process(self)
       wx.Execute(cmd, wx.EXEC_ASYNC, self.process)

       self.dlg = ConvertProgress(self)
       self.dlg.ShowModal()

   def on_end_process(self, event):
       """
       Destroy the progress Gauge/process after the convert process returns
       """
       self.process.Destroy()
       self.dlg.Destroy()
       del self.dlg
       del self.process

class ConvertProgress(wx.Dialog):
   """
   Shows a Progres Gauge while file conversion is taking place.
   """

   def __init__(self, parent):
       """
       Defines a gauge and a timer which updates the gauge.
       """
       wx.Dialog.__init__(self, parent, title="Converting...", size=(250, 100))
       self.count = 0

       self.timer = wx.Timer(self)
       self.gauge = wx.Gauge(self, range=100, size=(180, 30))

       sizer = wx.BoxSizer(wx.VERTICAL)
       sizer.Add(self.gauge, 0, wx.ALL, 5)
       self.SetSizer(sizer)
       sizer.Fit(self)
       self.SetFocus()

       self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
       self.timer.Start(20)

   def on_timer(self, event):
       """
       Increases the gauge's progress.
       """
       self.count += 1
       self.gauge.SetValue(self.count)
       if self.count == 100:
           self.count = 0

Hopefully that should give you an idea of what to do :slight_smile:
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Thank you Phil, I will try that.

···

----- Original Message ----
From: Phil Mayes <olivebr@olivebr.com>
To: wxpython-users@lists.wxwidgets.org
Sent: Friday, March 6, 2009 10:24:58 AM
Subject: Re: [wxpython-users] Running a progress bar and a subprocess.call at the same time

At 09:56 AM 3/6/2009, you wrote:

Hello wxpython community,

I need to display a progress bar while a an R program is running in the
background. I am not sure how to this. The following is what I have, but
doing it this way, the timer doesn't start. I am guessing the
subprocess.call should be placed somewhere else, but I am not sure where.
As always, your help is very appreciated.

Thank you.

Here is the code:

import subprocess
import wx

class MyFrame(wx.Frame):
    def __init__(self,parent,id, title, tpval=""):
        wx.Frame.__init__(self,parent,id,title='An
application',size=(900,750))

        self.SetBackgroundColour('tan')
        menuBar=wx.MenuBar()

        menu0=wx.Menu()
        menu0.Append(97, "&Open file","")
        menuBar.Append(menu0,"&File")

        self.Bind(wx.EVT_MENU,self.openfile,id=97)

    def openfile(self,event):

        dlgg=wx.FileDialog(self,"Choose a file",os.getcwd(),"","*.*",wx.OPEN)
        if dlgg.ShowModal() == wx.ID_OK:

            frame6=analysis(self,-1, "")
            frame6.Show(True)
dlgg.Destroy

class analysis(wx.Frame):
    def __init__(self,parent,id,title):
        wx.Frame.__init__(self,None,-1,title="Running analysis",
size=(350,150))

panel55=wx.Panel(self,-1)

        self.count=0
        self.timer=wx.Timer(self,-1)
        self.Bind(wx.EVT_TIMER,self.OnTimer,self.timer)

        self.gauge=wx.Gauge(panel55,-1,100,(20,50),(250,25))
        self.gauge.SetBezelFace(3)
        self.gauge.SetShadowWidth(3)
        self.timer.Start(100)

    def OnTimer(self,event):
# This is where the R process is called.
        command0='R CMD BATCH myRscript.R'
        subprocess.call(command0,shell=True)
        self.count=self.count+1
        self.gauge.SetValue(self.count)
        if self.count==100:
            self.timer.Stop()
            self.Close()

class MyApp(wx.App):
    def OnInit(self):
        myframe=MyFrame(None,-1,"commondialogs.py")
        myframe.Center
        myframe.Show(True)

app=MyApp(0)
app.MainLoop()

You're calling the sub-process every tick, and also waiting for it to
complete. You want to (a) call it in the __init__ code (b) call it so it
starts the process and returns immediately. Look at Popen and poll().
Probably
     self.proc = subprocess.Popen((["/bin/mycmd", "myarg"])
and in the timer loop:
     self.proc.poll()

I'm not an expert - you may need to tweak this. Phil

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users