python apscheduler、任务可以是死循环吗_flask_apscheduler 定时任务踩坑记录

背景

由于需要再flask做一个定时任务,然后发现了这个库flask_apscheduler.使用很简单,就是可能由于某种情况,会有一些意外,下面是我的使用记录。

首先按照官方文档跑一个示例

from flask import Flask

from flask_apscheduler import APScheduler

class Config(object):

JOBS = [

{

'id': 'job1',

'func': 'jobs:job1',

'args': (1, 2),

'trigger': 'interval',

'seconds': 10

}

]

SCHEDULER_API_ENABLED = True

def job1(a, b):

print(str(a) + ' ' + str(b))

if __name__ == '__main__':

app = Flask(__name__)

app.config.from_object(Config())

scheduler = APScheduler()

# it is also possible to enable the API directly

# scheduler.api_enabled = True

scheduler.init_app(app)

scheduler.start()

app.run()

'func': 'jobs:job1', 配置文件中这一行,代表任务。jobs代表这个文件名。job1是自己创建的任务函数。

ok,这里没有任何问题

问题1:在实际项目中,不可能都放在同一个文件下,创建一个任务时,找不到这个任务

如,我定义一个start函数,用于执行定时任务,这个start在app.models.ali路径下。问题原因是:'func': 'app:start'配置格式等有误,正确应该按照自己任务文件的实际路径,格式为:'func': 'app:models.ali.start',如下:

class Config:

JOBS = [

{

'id': 'job1',

'func': 'app:models.ali.start',

'trigger': 'cron',

'day_of_week': 'mon-fri',

'second': 1,

'hour': 9,

'minute': 30

}

]

SCHEDULER_API_ENABLED = True

问题2:在model文件里使用SQLAlchemy时,报错类似:No application found.flask-apsched Either work inside a view function or pus,也就是无法在任务函数中使用SQLAlchemy。解决办法:

app的__init__.py关键代码:

from flask_apscheduler import APScheduler

scheduler = APScheduler()

def create_app(config_name):

app = Flask(__name__, template_folder='templates')

app.config.from_object(config.get(config_name) or config['default'])

...

scheduler.init_app(app)

scheduler.start()

return app

然后我的任务start在app.models.ali路径下,需要在ali.py下:

from app import scheduler

def start():

with scheduler.app.app_context():

results = AliServers.query.all()

···

添加上下文后,就可以使用AliServers.query.all()这种操作了。

问题3:

本机开发环境下,一切正常,然后部署到服务器上,出错:

Traceback (most recent call last):

File "test.py", line 29, in

scheduler = APScheduler()

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/flask_apscheduler/scheduler.py", line 36, in __init__

self._scheduler = scheduler or BackgroundScheduler()

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 87, in __init__

self.configure(gconfig, **options)

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 126, in configure

self._configure(config)

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/apscheduler/schedulers/background.py", line 29, in _configure

super(BackgroundScheduler, self)._configure(config)

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 697, in _configure

self.timezone = astimezone(config.pop('timezone', None)) or get_localzone()

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/tzlocal/unix.py", line 165, in get_localzone

_cache_tz = _get_localzone()

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/tzlocal/unix.py", line 90, in _get_localzone

utils.assert_tz_offset(tz)

File "/root/.local/share/virtualenvs/flask-fUo2koNK/lib/python3.6/site-packages/tzlocal/utils.py", line 38, in assert_tz_offset

raise ValueError(msg)

ValueError: Timezone offset does not match system offset: 28800 != -14400. Please, check your config files.

根据错误信息查看源码,解决办法:

主要是两个地方:

首先查看服务器时区是上海,然后需要修改两个地方:

在配置文件中添加SCHEDULER_TIMEZONE = 'Asia/Shanghai',即:

class Config:

JOBS = [

{

'id': 'job1',

'func': 'app:models.ali.start',

'trigger': 'cron',

'day_of_week': 'mon-fri',

'second': 1,

'hour': 9,

'minute': 30

}

]

SCHEDULER_TIMEZONE = 'Asia/Shanghai'

SCHEDULER_API_ENABLED = True

然后在app的__init__.py下,添加BackgroundScheduler(timezone="Asia/Shanghai"):

from flask_apscheduler import APScheduler

from apscheduler.schedulers.background import BackgroundScheduler

scheduler = APScheduler(BackgroundScheduler(timezone="Asia/Shanghai"))

def create_app(config_name):

app = Flask(__name__, template_folder='templates')

app.config.from_object(config.get(config_name) or config['default'])

...

scheduler.init_app(app)

scheduler.start()

return app

原因是:时区会被解析两次,如果没有加时区,就会调用默认的self.timezone = astimezone(config.pop('timezone', None)) or get_localzone(),由于时区与系统不匹配,会报错。当然这个错误并不是每个机器都有,正巧,这台服务器的时区与系统偏移不一致,导致出现这个错误。

你可能感兴趣的:(python,apscheduler,任务可以是死循环吗)