josiahcarlson / parse-crontab Goto Github PK
View Code? Open in Web Editor NEWParse and use crontab schedules in Python
License: GNU Lesser General Public License v2.1
Parse and use crontab schedules in Python
License: GNU Lesser General Public License v2.1
>>> import crontab
>>> crontab.CronTab("0 5 * * * /path/to/my/applications/cronjob.sh # should be executed by the application's own user")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/crontab/_crontab.py", line 277, in __init__
self.matchers = self._make_matchers(crontab)
File "/usr/local/lib/python2.6/dist-packages/crontab/_crontab.py", line 285, in _make_matchers
for which, entry in enumerate(crontab.split())]
File "/usr/local/lib/python2.6/dist-packages/crontab/_crontab.py", line 166, in __init__
al, en = self._parse_crontab(which, it)
File "/usr/local/lib/python2.6/dist-packages/crontab/_crontab.py", line 252, in _parse_crontab
entry, increment = entry.split('/')
ValueError: too many values to unpack
I read the comments made in #10 about handling timezones and DST transitions. The solutions given is is inadequate, because parse-crontab, after calculating the future datetime, computes the timedelta between the future and the passed in now (tz-aware) datetime.
To see why consider the following example:
dt = datetime(2016, 03, 13, hour=5, minute=0, tzinfo=est) # where est is the America/New_York implementation
print CronTab("00 09 13 MAR *").next(dt)
The output is 4 hours, instead of 5 hours, because next() does the following sub operation (line 390 of master)
delay = future - dt # i.e. 2016-03-13 09:00:00-04:00 - 2016-03-13 05:00:00-05:00
That operation does not return the expected delay because, according to the python docs:
Subtraction of a datetime from a datetime is defined only if both operands are naive, or if both are aware. If one is aware and the other is naive, TypeError is raised.
If both are naive, or both are aware and have the same tzinfo attribute, the tzinfo attributes are ignored, and the result is a timedelta object t such that datetime2 + t == datetime1. No time zone adjustments are done in this case.
Which makes sense, because, I think, the intent was to have datetime arithmetic operations and timedelta objects have the Group property (i.e. behave similar to regular integers). If tzinfo attributes were considered when calling sub, then datetime2 + t would not equal datetime1.
But I don't think parse-crontab should behave similarly, because the result of a next() isn't a timedelta, but the number of seconds between the datetime passed in and the schedule.
Right now, i can get around this by adding the number of seconds returned to the passed in dt argument of next(), normalize the resulting future datetime and then compute the difference, again, to get the true number of seconds till the schedule. But I think the onus of applying the tzinfo to datetime for computations should be on parse-crontab and not the client.
Please install process in readme.md
then, pip install crontab
Create a package for this on conda-forge that tracks this repo.
Currently this project is not published to conda-forge.
I have tried installing crontab as:
> pip install crontab
and as:
> pip install git+git://github.com/josiahcarlson/parse-crontab
on both Python 2.7.x and Python 3.4.x without luck.
However, whenever I invoke:
from crontab import CronTab
system_cron = CronTab()
my_user_cron = CronTab(user=True)
users_cron = CronTab(user='dataxu')
I get:
> system_cron = CronTab()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-4132e81e1caa> in <module>()
----> 1 system_cron = CronTab()
TypeError: __init__() missing 1 required positional argument: 'crontab'
Why?
I'd like to schedule a task to run every 30 seconds. Is this possible with parse-crontab? Would you be interested in a PR to add support for it?
I started getting this error after 1am today, which is during the daylight savings time changeover:
next_alarm = CronTab(alarm.crontab).next(now=now, default_utc=False)
File /lib/crontab/_crontab.py", line 438, in next
delay += tz.utcoffset(now)
File "/python27/python27_lib/versions/third_party/pytz-2017.2/pytz/tzinfo.py", line 408, in utcoffset
dt = self.localize(dt, is_dst)
File "/python27/python27_lib/versions/third_party/pytz-2017.2/pytz/tzinfo.py", line 349, in localize
raise AmbiguousTimeError(dt)
AmbiguousTimeError: 2018-11-04 01:00:48.901902
The code I am using is roughly this:
timezone = pytz.timezone("America/Los_Angeles")
now = pytz.utc.localize(datetime.datetime.utcnow()).astimezone(timezone)
next_alarm = CronTab("30 8 * * MON-FRI").next(now=now, default_utc=False)
Hi,
Upgrading crontab to 0.21.x from 0.20.x caused problems in my script. My timezone is Australia/Sydney.
System details:
Ubuntu 14.04
Python version: 2.7.6
I used the following script to illustrate the problem:
import datetime
from crontab import CronTab
print 'Local date:', datetime.datetime.now()
c = CronTab('* 9-17 * * MON-FRI')
print c.next()
me@server:~/tmp$ date
Wed Apr 20 15:21:13 AEST 2016
me@server:~/tmp$ python t.py
Local date: 2016-04-20 15:21:14.964162
45.035433
me@server:~/tmp$ date
Wed Apr 20 15:22:23 AEST 2016
me@server:~/tmp$ python t.py
Local date: 2016-04-20 15:22:25.686065
13054.313699
Thanks
Dirk
Hi.
I was doing some testing and noticed when I use the pattern 0 0 */30 * *
it did not yield expected results.
from crontab import CronTab
from datetime import datetime, timedelta
entry = CronTab('0 0 */30 * *')
dt = datetime(2021, 10, 31)
last = dt
for i in range(5):
secs = entry.next(dt)
dt += timedelta(seconds=secs)
print(dt.isoformat(), "diff = ", dt - last)
last = dt
> output
2021-11-01T00:00:00 diff = 1 day, 0:00:00
2021-12-01T00:00:00 diff = 30 days, 0:00:00
2021-12-31T00:00:00 diff = 30 days, 0:00:00
2022-01-01T00:00:00 diff = 1 day, 0:00:00
2022-01-31T00:00:00 diff = 30 days, 0:00:00
but i'm expecting something like
dt = datetime(2021, 10, 31)
last = dt
for i in range(5):
dt += timedelta(days=30)
print(dt.isoformat(), "diff = ", dt - last)
last = dt
> output
2021-11-30T00:00:00 diff = 30 days, 0:00:00
2021-12-30T00:00:00 diff = 30 days, 0:00:00
2022-01-29T00:00:00 diff = 30 days, 0:00:00
2022-02-28T00:00:00 diff = 30 days, 0:00:00
2022-03-30T00:00:00 diff = 30 days, 0:00:00
My understanding is that */30
means every 30 units.
From the crontab man page:
Step values are also permitted after an asterisk, so if
specifying a job to be run every two hours, you can use "*/2".
I get a mail notice after the cron job.
I edit the cronjob by adding 2>&1
to avoid this.
But is there any way I can stop sending an email for each job from cronTab?
15 10 * * * bash /Users/shinokada/Cron/daily_bubu >/dev/null 2>&1
# bubu
0 10 2-30/2 * * bash /Users/shinokada/Cron/cleanit_job>/dev/null 2>&1
# daily_clean
Hi!
I just wanted to download the latest release tarball which includes tests.
However, since there is no 0.23.0
release tag, Github is not generating a tarball.
Could you add the missing tags?
Thanks,
Adrian
Hi,
i've this crontab entry: */30 23-05 * * *
And i receive an assertion error:
ValueError: range start value 23 > end value 5
But my crontab is from 23 to 5 works.
Please update
for example:
crontab.CronTab('77 * * * *').next() - hangs the script for a long time (100% CPU usage) and returns None
I'm having a bit of confusion in figuring this out. I have something that will wake up every minute ( via a linux cron job ) and figure out which "pythonic" things it needs to run via cron syntax provided by this module. For things that are in ranges, i.e. * 12-12 * * mon-fri
its working fine, but for things that are static like, 0 0 * * *
, I'm having troubles when our current time meets the cron time.
Here is a code example of what I'm referring to:
import datetime
import pytz
from crontab import CronTab
# Run something at midnight every day
cronstr = "0 0 * * *"
now = datetime.datetime(2016, 01, 01, 00, 00, 00, 00, pytz.UTC)
print(now)
>>> 2016-01-01 00:00:00+00:00
entry = CronTab(cronstr)
seconds_until_next_run = entry.next(now)
print(seconds_until_next_run)
>>> 86400.0
I would expect the value of seconds_until_next_run
to be 0
instead of 86400
, since we are testing this at midnight at literally the same time this cron entry should match. Checking entry.previous(now)
results in -86400.0
and I would think previous
should be 0
as well.
Is there any to accomplish what I need to do with this module? Is possible I'm missing something ( typically the case ) , but figured I would ask anyways.
I have periodical job, run every minute. In this job a have own cron rule. I want to skip the next job starting, if sheduling time of my own rule is not come.
For example. Sheduler run every minute, but my job must run every day on 12 o clock.
# this code run every munite
now = datetime.now()
last_start = job.last_start
c = CrontTab('0 12 * * *')
duration = c.next(now, last_start)
if duration < 0:
job.run()
It is possible to do this?
Thanks a lot!
Cron expressions such as "0 0 1-7 * 4" (first thursday of every month) is not supported by your library.
The error is caused by these code:
if not matchers.day.any:
_assert(matchers.weekday.any,
"missing a wildcard specifier for weekday")
if not matchers.weekday.any:
_assert(matchers.day.any,
"missing a wildcard specifier for day")
in the CronTab._make_matchers method.
So for cron spec frequency '0/15 * * * *' is a valid cron string as per parse-crontab but centos rejects it as per the crontab specification.
As Per the crontab(5) man page on CentOS 7,Step values can be used in conjunction with ranges andStep values are also permitted after an asterisk. The /15 is a step value and since the 0 in 0/15 is neither a range nor an asterisk, the crontab Linux utility rejects it.
Such an error results in failure for updating cronjobs trying to set with this cron frequency.
The release that just went to PyPi is completely broken.
Running setup.py (path:/build/crontab/setup.py) egg_info for package crontab
Traceback (most recent call last):
File "", line 17, in
File "/build/crontab/setup.py", line 3, in
from ez_setup import use_setuptools
ImportError: No module named ez_setup
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 17, in
File "/build/crontab/setup.py", line 3, in
from ez_setup import use_setuptools
ImportError: No module named ez_setup
I basically cloned the repository into a new virtual environment and pip installed ./ to see if everything worked. The output was ModuleNotFoundError: No module named 'pytz'
which probably should be listed as dependency
Given an entry in crontab
, e.g.:
10 13 * * * my_script.sh
Can parse-crontab
help me get the list of `datetimes this entry will run in the machine within the next X days? (e.g. next week).
I went through the README.md
but I am not sure I understand exactly how the package functionality could relate to this problem.
Could you please create a MANIFEST.in
file and add the license files to it so they will be included in the packages that are distributed on PyPI?
Came across this case where if the day of the month is also specified along with day of the week (eg. Friday the 13th), it results in a ValueError
In [59]: import crontab
In [60]: crontab.CronTab('* * 13 * Fri *')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-60-7bef4be30389> in <module>()
----> 1 crontab.CronTab('* * 13 * Fri *')
/Library/Python/2.7/site-packages/crontab/_crontab.pyc in __init__(self, crontab)
324 __slots__ = 'matchers',
325 def __init__(self, crontab):
--> 326 self.matchers = self._make_matchers(crontab)
327
328 def _make_matchers(self, crontab):
/Library/Python/2.7/site-packages/crontab/_crontab.pyc in _make_matchers(self, crontab)
342 if not matchers.day.any:
343 _assert(matchers.weekday.any,
--> 344 "missing a wildcard specifier for weekday")
345 if not matchers.weekday.any:
346 _assert(matchers.day.any,
/Library/Python/2.7/site-packages/crontab/_crontab.pyc in _assert(condition, message, *args)
164 def _assert(condition, message, *args):
165 if not condition:
--> 166 raise ValueError(message%args)
167
168 class _Matcher(object):
ValueError: missing a wildcard specifier for weekday
When day of month is not specified, it works fine
In [61]: crontab.CronTab('* * * * Fri *')
Out[61]: <crontab._crontab.CronTab at 0x103f68e50>
Not sure if this is a valid combination to use as per the cron spec as I didn't find anything mentioned about it here - https://en.wikipedia.org/wiki/Cron#CRON_expression.
I believe I am having an issue between the usage examples from nameconflicts between the listed pypi crontab and python-crontab. Could you shortly elaborate on correct install method or navigating around these problems?
I'm either getting no module named crontab
or takes exactly 2 arguments
errors, depending on what I uninstalled/re-installed.
Sorry for the nooby question, and thanks!
If an we compare a CronTab
object with None
, an exception occurs:
cron = crontab.CronTab("* * * * *")
if cron == None:
pass
AttributeError: 'NoneType' object has no attribute 'matchers'
The problem is in the definition of CronTab.__eq__()
.
parse-crontab/crontab/_crontab.py
Lines 388 to 389 in ccf931e
If other
is not an instance of CronTab
, we should directly return False
without going further.
I can do a pull request for this.
What we wish had happened?
when using string * 3 * * *
we should run the job every minute between 3 and 4 am.
What actually happens?
job runs every minute.
The Python packaging world is moving towards normalized version numbers described in PEP 386 (the currently accepted standard) and PEP 440 (new draft intended to replace PEP 386).
Please use a version number like 0.17
instead of just .17
for the next release, to be compatible with the PEPs.
(Personally, I prefer changing the version number in setup.py to '0.17.dev0' right after I release 0.16, and then change it to '0.17' just before I release it, so that a random checkout could not be confused with a released version).
I am working against a remote machine whose local time is UTC. My own local time is ET (Eastern Time). Does parse-crontab
handle time-zone differences?
The recent release (0.22.3) causes a new issue.
The message AttributeError: 'tzlocal' object has no attribute 'localize'
occurs when calling the next()
method with a default_utc=True
and a now=datetime
arguments.
The input datetime (to the now
argument) is datetime.utcnow()
.
This is exactly in the lines changed in the 0.22.3 release and was not an issue in 0.22.2.
It seems that this warning message may not be accurate anymore and can be a bit misleading?
FutureWarning: Version 0.22.0+ of crontab will use datetime.utcnow() and
datetime.utcfromtimestamp() instead of datetime.now() and
datetime.fromtimestamp() as was previous. This had been a bug, which will be
remedied. If you would like to keep the *old* behavior:
`ct.next(..., default_utc=False)` . If you want to use the new behavior *now*:
`ct.next(..., default_utc=True)`. If you pass a datetime object with a tzinfo
attribute that is not None, timezones will *just work* to the best of their
ability. There are tests...
The warning suggest that for version >= 0.22 the default_utc
parameter will default to True
if not specified. However that does not appear to be the case in version 1.0.1, and if I understand correctly the default is still the "old" behavior?
I'm unsure what the best solution would be here to resolve this:
default_utc
to True
if not specified and remove the warning.1.1
?)A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.