title: Take screenshots at fixed intervals with Python using threading.Timer
body: <p>I'm writing a simple GUI application with pyGTK to take desktop screenshots at fixed intervals. To schedule the shots I use the threading.Timer class and to take shots I use os.system calls to scrot.</p>
  
  <p>When I click the start taking screenshots button the GlapseMain.startScreenshots method is called. When I click the stop taking screenshot button the GlapseMain.stopScreenshots method is called.</p>
  
  <p>The thing is while the GTK app is working no screenshot is taken although it should. When I click the close button, it starts taking screenshots idefinitely.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>#!/usr/bin/env python
  # -*- coding: utf8  -*-
  
  import threading
  import os
  
  class GlapseMain:
  
  def __init__(self):
      self.outputDir = os.getenv('HOME')
      self.quality = 80
      self.interval = 10
      self.numDigits = 15
      self.currentShot = 0
  
  def startScreenshots(self, output, quality, interval):
      print 'Starting taking screenshots...'
      print 'Output folder: ' + str(output)
      print 'Quality: ' + str(quality)
      print 'Interval: ' + str(interval)
  
      # Update attributes
      self.outputDir = output
      self.quality = quality
      self.interval = interval
      self.currentShot = 0
  
      # Create timer (first screenshot scheduled 1s ahead)
      self.timer = threading.Timer(1.0, self._takeScreenshot)
      self.timer.start()
  
  
  def stopScreenshots(self):
      print 'Stopped taking screenshots.'
  
      self.timer.cancel()
  
  
  def _takeScreenshot(self):
      # Build scrot command
      fileNumber = str(self.currentShot)
      fileNumber = fileNumber.zfill(self.numDigits - len(fileNumber))
      fileName = 'scr-' + fileNumber + '.jpg'
  
      command = 'scrot -q ' + str(self.quality) + ' ' + self.outputDir + os.sep + fileName
  
      print 'Taking screenshot: ' + command + '...'
  
      os.system(command)
  
      # Schedule next screenshot
      self.currentShot = self.currentShot + 1
      self.timer = threading.Timer(self.interval, self._takeScreenshot)
      self.timer.start()
  </code></pre>
  
  <p>My output looks something like this:</p>
  
  <pre><code>Starting taking screenshots...
  Output folder: /home/david/glapse-screens
  Quality: 80.0
  Interval: 2.0
  Stopped taking screenshots.
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000000.jpg...
  Closing gLapse...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000001.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000002.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000003.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000004.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000005.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000006.jpg...
  Taking screenshot: scrot -q 80.0 /home/david/glapse-screens/scr-00000000000007.jpg...
  </code></pre>
  
  <p>Hope you could help me, thank you very much.</p>
  
  <p>Edit:</p>
  
  <p>I've changed the approach and now I'm using threads:</p>
  
  <pre><code>def startScreenshots(self, output, quality, interval):
      print 'Starting taking screenshots...'
      print 'Output folder: ' + str(output)
      print 'Quality: ' + str(quality)
      print 'Interval: ' + str(interval)
  
      # Update attributes
      self.outputDir = output
      self.quality = quality
      self.interval = interval
      self.currentShot = 0
  
      # Start a thread to take screenshots
      self.done = False
      self.thread = threading.Thread(target=self._takeScreenshot)
      self.thread.start()
  
  def stopScreenshots(self):
      print 'Stopped taking screenshots.'
      self.done = True
      self.thread.join()
  
  
  def _takeScreenshot(self):
      # Run until we're done
      while not self.done:
          # Build scrot command
          fileNumber = str(self.currentShot)
          fileNumber = fileNumber.zfill(self.numDigits - len(fileNumber))
          fileName = 'scr-' + fileNumber + '.jpg'
  
          command = 'scrot -q ' + str(self.quality) + ' ' + self.outputDir + os.sep + fileName
  
          print 'Taking screenshot: ' + command + '...'
  
          os.system(command)
  
          # Schedule next screenshot
          print 'Scheduling next screenshot...'
          self.currentShot = self.currentShot + 1
          time.sleep(self.interval)
  </code></pre>
  
  <p>It prints the message but not executes the os.system instruction until I press the stop button.</p>