项目的定时任务有用到Django的环境变量,必须在其下执行,所以选用django_crontab,其本质也就是Linux的crontab,调用也简单,不赘述,但是,给调用的方法传参的时候老报错:
TypeError, argument after ** must be a mapping,not str
翻看官网文档,没什么发现;
我传参用的是: (‘0 0 1 * *’, ‘myapp.cron.other_scheduled_job’, [‘myapp’]),比它多的是我有个输出重定位,‘>> /home/appadmin/logs/crontab.log’,如下:
(‘0 0 1 * *’, ‘myapp.cron.other_scheduled_job’, [‘myapp’], ‘>> /home/appadmin/logs/crontab.log’),然后就摊上事了,调了大半天,也没发现问题所在。一开始甚至不知道在哪里看报错信息!!!
CRONJOBS = [
('*/5 * * * *', 'myapp.cron.my_scheduled_job'),
# format 1
('0 0 1 * *', 'myapp.cron.my_scheduled_job', '>> /tmp/scheduled_job.log'),
# format 2
('0 0 1 * *', 'myapp.cron.other_scheduled_job', ['myapp']),
('0 0 * * 0', 'django.core.management.call_command', ['dumpdata', 'auth'], {'indent': 4}, '> /home/john/backups/last_sunday_auth_backup.json'),
]
后来在Linux执行crontab -e, 找到了django放进去的定时任务,然后,复制执行时间后边的任务体,拿出来,手动执行,才看到报错信息,如上;
然后分析报错,各种查,没有类似事件;
然后,自己各种实验,发现不传参可以,发现只要传参,位置传和关键字传都不可以,再发现,去掉后边的输出重定向,可以了!!!
最后,分析源码(其实没有想象的深奥,就是split任务字符串,执行什么的),逐渐明晰,感觉是这个模块的bug,在此记录一下:
源码的crontab.py下,121-129行,
# noinspection PyBroadException
def run_job(self, job_hash):
"""
Executes the corresponding function defined in CRONJOBS
"""
job = self.__get_job_by_hash(job_hash)
job_name = job[1]
job_args = job[2] if len(job) > 2 and not isinstance(job[2], string_type) else []
job_kwargs = job[3] if len(job) > 3 else {}
可以看到它去判断元祖的长度,单纯的认为第一项是方法名,第二项是位置参数,关键来了,第三项是关键字参数!!!
合着把我的输出重定向当做关键字传参了,怪不得报mapping的错误,我看了它提取job的方式,也没有深度处理,所以觉得这个地方粗暴了
但是吧,你不传参的时候,这个重定向是可以用的,也不会被当做参数项来解析,神奇了。