Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Run Job every first Monday of month

Background: I need to run automatic tasks every first and third monday of the month for a server. This should be realised via python not crontab.

I found the python module "schedule" but its documentation is not detailed. https://pypi.org/project/schedule/

https://schedule.readthedocs.io/en/stable/

Does anybody know how to do this?

import schedule

def TestFunction():
    pass

schedule.every(1).monday.do(TestFunction)
schedule.every(3).monday.do(TestFunction)
schedule.run_pending()

Will this be executed on the first monday of the year, month or every monday?

like image 575
NikolaTesla Avatar asked Jun 30 '19 11:06

NikolaTesla


2 Answers

Here's a possible solution:

import datetime

def something():
    day_of_month = datetime.now().day
    if (day_of_month > 7 and day_of_month < 15) or day_of_month > 21:
        return # not first / third monday of month
    # your code

schedule.every().monday.do(something())

The scheduler will run every monday, but we return if this is not the first / third monday of the month.

like image 85
AdamGold Avatar answered Sep 29 '22 03:09

AdamGold


It seems that for now, this functionality is not implemented in schedule package:

schedule.every(3).monday.do(test)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/schedule/__init__.py", line 302, in monday
    raise IntervalError('Use mondays instead of monday')
schedule.IntervalError: Use mondays instead of monday
>>> schedule.every(3).mondays.do(test)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Job' object has no attribute 'mondays'

I would suggest to use a while True loop, and manually check if the very day is the first monday of the month:

from datetime import datetime, date
import calendar

def find_first_monday(now):
    month_range = calendar.monthrange(now.year, now.month)
    date_corrected = date(now.year, now.month, 1)
    delta = (calendar.MONDAY - month_range[0]) % 7
    if not delta:
        return True
    return False

while True:
     now = datetime.now()
     if first_monday_of_the_month(now):
          TestFunction()
          time.sleep(24*3600)
like image 26
sashaboulouds Avatar answered Sep 29 '22 04:09

sashaboulouds