4

I want to take a screenshot every second for 10 secs.

I have tried using threading and schedule but I've not been able to come up with the solution to satisfy my problem.

def fun(original):
    end_time = datetime.now() + timedelta(seconds=10)
    while datetime.now() < end_time:
        current = ImageGrab.grab()
        current.save("current.png")
        current = cv2.imread("current.png")
        found = screenshot_comparison(original,current)
        if found :
            print("matched")
        else :
            print("didntMATCH")
            fun(original)

I want to take screenshots every second for 10 secs and match it with an already grabbed screenshot.

HansHirse
  • 18,010
  • 10
  • 38
  • 67
Shreyash Sharma
  • 310
  • 2
  • 11
  • 1
    Could you explain why this solution don't satifsy you? – Arount Sep 12 '19 at 09:59
  • 1
    Possible duplicate of [How do I get a Cron like scheduler in Python?](https://stackoverflow.com/questions/373335/how-do-i-get-a-cron-like-scheduler-in-python) – Somil Sep 12 '19 at 10:14
  • Looking the code it must work, but the script is not stopping, its continuously running. I think it has something to do with the recursive call, but cannot properly understand why. @Arount – Shreyash Sharma Sep 12 '19 at 10:19
  • As an aside, you probably want to separate the collection of the screenshots from their use – Reblochon Masque Sep 12 '19 at 10:26
  • I don't see any recursive calls, maybe because you didn't post the entire relevant code. Anyway, if there is indeed a call to `fun()` inside `screenshot_ comparison` or `screenshot_continous` , then it's no wonder it isn't stopping. And then even if there is no recursive call, there is nothing in the while loop to limit it to taking screenshots once a second, it grabs them as often as it can. – IcedLance Sep 12 '19 at 10:33
  • Sorry, changed the code. There was a problem while pasting here. – Shreyash Sharma Sep 12 '19 at 10:42
  • As for the loop, let's say datetime.now() = x; end_time = x + 3; the loop should stop as datetime.now() will increase and eventually be greater than end_time. Or am I missing something @IcedLance :) – Shreyash Sharma Sep 12 '19 at 10:47
  • @shreyashsharma If there is no recursive call then it is okay except it loops as fast as it can, not waiting for 1 second to pass (you were suggested to put sleep(1) to fix it. If there IS a recursive call inside loop however then a new instance of fun() will start and it will create its own new end_time (that will be a bit later as it was called later) and so on. – IcedLance Sep 12 '19 at 10:52
  • I've looked at your edited code and here's the problem: if nothing changes on the screen, then it's fine, but if something does change, then it will continue to call fun recursively due to the reason i described. On the other hand, if you change it to `fun(current)` then it will stop once screen have been unchanged for 10 seconds straight. (However you might run into stackoverflow error eventually if it takes too long. – IcedLance Sep 12 '19 at 11:01

1 Answers1

4

I would suggest utilizing the Advanced Python Scheduler and more specifically, use their interval scheduler, for example:

sched = BlockingScheduler()
sched.add_job(yourFunction, 'interval', seconds=10)
sched.start()

EDIT Here's a more complete example:

from apscheduler.schedulers.blocking import BlockingScheduler

sched = BlockingScheduler()

def myFunction(testParam):
    print("Message: {}".format(testParam))

if __name__ == '__main__':
    sched.add_job(myFunction, 'interval', seconds=10, args=["Works!"])
    sched.start()
Lucan
  • 2,907
  • 2
  • 16
  • 30
  • it worked but while trying to call my function as sched.add_job(fun(original), 'interval', seconds=5), I am getting - TypeError: func must be a callable or a textual reference to one And if I change to - sched.add_job(screenshot_continous, 'interval', seconds=5) I am getting - ValueError: The following arguments have not been supplied: original – Shreyash Sharma Sep 12 '19 at 15:36
  • Take a look at the documentation for the [`add_job`](https://apscheduler.readthedocs.io/en/latest/modules/schedulers/base.html#apscheduler.schedulers.base.BaseScheduler.add_job) method, there is a parameter for passing arguments to your function. – Lucan Sep 12 '19 at 16:05
  • @shreyashsharma I've added another example for you – Lucan Sep 12 '19 at 16:21
  • just one last query, why isn't the execution stopping after the given time. – Shreyash Sharma Sep 12 '19 at 16:38
  • It's designed for repeated execution, I thought you wanted it to repeat every 10 seconds. Regardless, you can [pause](https://apscheduler.readthedocs.io/en/latest/modules/schedulers/base.html#apscheduler.schedulers.base.BaseScheduler.pause_job) the job (you just need to initialize it with a job ID which you can read the docs for) or you can [stop/pause](https://apscheduler.readthedocs.io/en/latest/userguide.html?highlight=shutting%20down#shutting-down-the-scheduler) the entire scheduler – Lucan Sep 13 '19 at 08:08
  • No it was to repeat every 1 sec for 10 sec. But I did it by executing another job 10 sec later to stop all jobs. – Shreyash Sharma Sep 13 '19 at 12:36