Take screenshots at fixed intervals with Python using threading.Timer

I am writing a simple graphical application with pyGTK to take screenshots on a computer at fixed intervals. To schedule frames, I use the threading.Timer class and take snapshots. I use os.system calls for scrot.

When I press the start button, I launch the screenshot button, the GlapseMain.startScreenshots method is called. When I click the freeze button, the GlapseMain.stopScreenshots method is called.

The fact is that the GTK application works without a screenshot, although it should be. When I click the close button, it starts to take screenshots definitely.

Here is my 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() 

My output looks something like this:

 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... 

Hope you could help me, thank you very much.

Edit:

I changed the approach and now use streams:

 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) 

It prints a message, but does not execute the os.system command until I press the stop button.

+7
source share
1 answer

In reply:

You also need to call

 gtk.gdk.threads_init() 

before gtk.main () is called if you want streams with gtk


Let _takeScreenshot () have a while loop and not start a new thread for the next screenshot. You already have a workflow for this, for example

You also need a thread instead of a timer

 def _takeScreenshot(self): while self.notDone: # take screen shot # .. time.sleep(self.interval) 

Then in your undo method do something like:

 def stopScreenshots(self): self.notDone = False self.timer.join() # wait for thread to finish 
+4
source

All Articles