【问题标题】:Python running a cron job every 20 secondsPython 每 20 秒运行一次 cron 作业
【发布时间】:2018-03-22 22:32:59
【问题描述】:

我总是使用 celery 周期性任务来运行 cron,但是这次 celery 的 crontab 无法完成我的 cronjob。我需要一个只在星期二的 20:50 到 21:10 每 20 秒运行一次的 cron。似乎无法做到这一点

【问题讨论】:

    标签: python cron celery


    【解决方案1】:

    您可以将 python 脚本添加到系统的 crontab 中,也可以自己编写代码。只需启动一个新线程,计算到周二 20:50 的时间,然后一直休眠到那时,然后运行作业并休眠剩余的几秒钟,然后在 21:10 之后再次计算到周二 20:50 的时间。

    这可以使用命令time.time()time.sleep() 轻松完成。

    【讨论】:

      【解决方案2】:

      如果有人想在几秒钟内启用运行 celery 的 crontab;下面是一个通过扩展 crontab 的例子

      from celery.schedules import crontab, cronfield
      from celery.utils.timeutils import ffwd
      
      CRON_REPR = '''\
      <crontab: {0._orig_second} {0._orig_minute} {0._orig_hour} {0._orig_day_of_week} \
      {0._orig_day_of_month} {0._orig_month_of_year} (s/m/h/d/dM/MY)>\
      '''
      
      class ExtendedCrontab(crontab):
          '''
          custom crontab to support 'seconds'
          '''
      
          def __init__(self, second=0, minute='*', hour='*', day_of_week='*',
                       day_of_month='*', month_of_year='*', nowfun=None, app=None):
              super().__init__(second, minute, hour, day_of_week, day_of_month,
                               month_of_year, nowfun, app)
              self._orig_second = cronfield(second)
              self.second = self._expand_cronspec(second, 60)
      
      
          def _delta_to_next(self, last_run_at, next_hour, next_minute, next_second):
              '''
              Takes a datetime of last run, next minute and hour, and
              returns a relativedelta for the next scheduled day and time.
              Only called when day_of_month and/or month_of_year cronspec
              is specified to further limit scheduled task execution.
              '''
      
              _ffwd = super()._delta_to_next(last_run_at, next_hour, next_minute)
              _ffwd.second = next_second
              return _ffwd
      
          def __repr__(self):
              return CRON_REPR.format(self)
      
          def __reduce__(self):
              return (self.__class__, (self._orig_second,
                                       self._orig_minute,
                                       self._orig_hour,
                                       self._orig_day_of_week,
                                       self._orig_day_of_month,
                                       self._orig_month_of_year), None)
      
          def remaining_delta(self, last_run_at, tz=None, ffwd=ffwd):
              tz = tz or self.tz
              last_run_at = self.maybe_make_aware(last_run_at)
              now = self.maybe_make_aware(self.now())
              dow_num = last_run_at.isoweekday() % 7  # Sunday is day 0, not day 7
              execute_this_date = (last_run_at.month in self.month_of_year and
                                   last_run_at.day in self.day_of_month and
                                   dow_num in self.day_of_week)
      
              execute_this_hour = (execute_this_date and
                                   last_run_at.day == now.day and
                                   last_run_at.month == now.month and
                                   last_run_at.year == now.year and
                                   last_run_at.hour in self.hour and
                                   last_run_at.minute < max(self.minute))
              execute_this_minute = (last_run_at.minute in self.minute and
                                     last_run_at.second < max(self.second))
              if execute_this_minute:
                  next_second = min(second for second in self.second
                                    if second > last_run_at.second)
                  delta = ffwd(second=next_second, microsecond=0)
              else:
                  if execute_this_hour:
                      next_minute = min(minute for minute in self.minute
                                        if minute > last_run_at.minute)
                      next_second = min(self.second)
                      delta = ffwd(minute=next_minute, second=next_second, microsecond=0)
                  else:
                      next_minute = min(self.minute)
                      next_second = min(self.second)
                      execute_today = (execute_this_date and
                                       last_run_at.hour < max(self.hour))
      
                      if execute_today:
                          next_hour = min(hour for hour in self.hour
                                          if hour > last_run_at.hour)
                          delta = ffwd(hour=next_hour, minute=next_minute,
                                       second=next_second, microsecond=0)
                      else:
                          next_hour = min(self.hour)
                          all_dom_moy = (self._orig_day_of_month == '*' and
                                         self._orig_month_of_year == '*')
                          if all_dom_moy:
                              next_day = min([day for day in self.day_of_week
                                              if day > dow_num] or self.day_of_week)
                              add_week = next_day == dow_num
      
                              delta = ffwd(weeks=add_week and 1 or 0,
                                           weekday=(next_day - 1) % 7,
                                           hour=next_hour,
                                           minute=next_minute,
                                           second=next_second,
                                           microsecond=0)
                          else:
                              delta = self._delta_to_next(last_run_at,
                                                          next_hour, next_minute,
                                                          next_second)
              return self.to_local(last_run_at), delta, self.to_local(now)
      
          def __eq__(self, other):
              if isinstance(other, crontab):
                  return (other.month_of_year == self.month_of_year and
                          other.day_of_month == self.day_of_month and
                          other.day_of_week == self.day_of_week and
                          other.hour == self.hour and
                          other.minute == self.minute and
                          other.second == self.second)
              return NotImplemented
      
      ExtendedCrontab(second=second,
                      minute=minute,
                      hour=hour,
                      day_of_week=day_of_week,
                      day_of_month=day_of_month,
                      month_of_year=month_of_year)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-20
        • 2018-02-18
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        • 2015-07-29
        • 2021-12-18
        • 2014-09-25
        相关资源
        最近更新 更多