Python: 3.8
APScheduler:3.6.3
# 不知道说明原因 不引用下面这个库 from flask_apscheduler import APScheduler 会报错。
Flask-APScheduler: 1.11.0
作为自己的笔记,我就不过多的说明了。这不是我擅长的部分。而且定时任务的很多参数这里面并没有记录,后续待补充(意味着:如果没有特别需求的情况下是不会有补充啦~)。
# 文件名称 weather.py
import requests
from flask import Flask
from flask_apscheduler import APScheduler
import configparser
import os
import sqlite3
import logging.config
"""
这是每隔5分钟去获取一次最新的天气情况。并保存到SQLite3数据库中的一个DEMO。
@auter joker create on 2020-03-21
"""
env = os.environ
HOST = env.get('HOST', default='0.0.0.0')
PORT = env.get('PORT', default=5000)
TIME_INTERVAL = env.get('TIME_INTERVAL', default=2)
FILE_NAME = env.get('FILE_NAME', default='./conf/cityCode.ini')
WEATHER_API = env.get('WEATHER_API', default='http://t.weather.sojson.com/api/weather/city/')
SQLITE_DATABASE = env.get('SQLITE_DATABASE', default='./conf/weather.db')
CITY_CODE = None
logging.config.fileConfig('./conf/weather.conf')
logger = logging.getLogger()
class APSchedulerJobConfig(object):
JOBS = [
# { # 每隔5S执行一次
# 'id': 'job',
# 'func': '__main__:method_test', # 方法名
# 'args': (1, 2), # 入参
# 'trigger': 'interval', # interval表示循环任务
# 'seconds': 5,
# },
{ # 每隔5M执行一次
'id': 'job1',
'func': '__main__:save_weather', # 方法名
'args': None, # 入参
'trigger': 'interval', # interval表示循环任务
'minutes': int(TIME_INTERVAL),
}
]
app = Flask(__name__)
# 为实例化的flask引入配置
app.config.from_object(APSchedulerJobConfig)
# ************** common *************
class SqliteTool(object):
def __init__(self):
self.conn = sqlite3.connect(database=SQLITE_DATABASE, timeout=3.0)
self.cursor = self.conn.cursor()
def save(self, temp):
try:
# 创建数据库
# cursor.execute("create table weather( id integer primary key autoincrement,
# temperature varchar(50), insertDate timestamp not null default (datetime('now','localtime')))")
sql = 'insert into weather (temperature, city, cityCode, humidity) values (?, ?, ?, ?)'
self.cursor.execute(sql, temp)
self.conn.commit()
self.cursor.close()
self.conn.close()
except Exception as e:
logger.error('数据持久化错误,请联系管理员 %s' % e)
def get_city_code(city):
"""
获取城市编码
:param city:
:return:
"""
global CITY_CODE
if CITY_CODE is None:
con = configparser.ConfigParser()
con.read(FILE_NAME, encoding='utf-8')
items = con.items('CityCode')
CITY_CODE = dict(items)
return CITY_CODE.get(city)
def get_context(code):
"""
获取天气数据
:param code:
:return:
"""
try:
url = WEATHER_API + code
with requests.get(url, stream=True, timeout=1.0) as r:
if r.status_code == 200:
return r.json()
else:
return None
except Exception as e:
r.close()
logger.error(e, '请求出错。')
finally:
r.close()
# ************** common *************
def save_weather():
# if city is None:
# city = '南京'
code = get_city_code('南京')
weather_json = get_context(code)
if weather_json is not None:
temp_data = [weather_json.get('data').get('wendu'), weather_json.get('cityInfo').get('city'),
weather_json.get('cityInfo').get('citykey'), weather_json.get('data').get('shidu')]
SqliteTool().save(temp_data)
else:
weather_json = ''
logger.info(weather_json)
return weather_json
# @app.route('/weather/<city>')
# def get_weather(city):
# result = save_weather(city)
# return jsonify(result), 200
@app.route("/hello")
def check():
return "success", 200
if __name__ == '__main__':
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
app.run(host=HOST, port=int(PORT), debug=False)
附上打包脚本及相关配置文件:
日志配置
# weather.conf
[loggers]
keys=root
[handlers]
keys=consoleHandler,rotatingFileHandler
[formatters]
keys=simpleFmt
[logger_root]
level=INFO
handlers=consoleHandler,rotatingFileHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFmt
args=(sys.stdout,)
[handler_rotatingFileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=simpleFmt
args=("./logs/weather.log", "a", 20*1024*1024, 10,'utf-8')
[formatter_simpleFmt]
format=%(asctime)s [ %(levelname)s ] %(message)s
datefmt=
城市编码
# citiCode.ini
北京=101010100
上海=101020100
广州=101280101
深圳=101280601
南京=101190101
溧水=101190102
高淳=101190103
江宁=101190104
六合=101190105
江浦=101190106
浦口=101190107
海淀=101010200
朝阳=101010300
顺义=101010400
怀柔=101010500
通州=101010600
昌平=101010700
延庆=101010800
丰台=101010900
石景山=101011000
;还有很多,就不一一列举。
SQLite3建库脚本
# 数据库脚本:
create table weather
(
id integer
primary key autoincrement,
temperature varchar(50),
insertDate timestamp default datetime('now', 'localtime') not null,
humidity varchar(50),
city varchar(20),
cityCode int
);
create index weather_insertDate_index
on weather (insertDate);
Dockerfile
# Dockerfile 源文件未加密。
#!/bin/bash
FROM python:3.6-alpine
ENV LANG C.UTF-8
ENV TZ Asia/Shanghai
WORKDIR /usr/src/app
RUN pip3 install --upgrade pip
RUN pip3 install requests==2.20.1
RUN pip3 install Flask==1.1.1
RUN pip3 install APScheduler==3.6.3
RUN pip3 install Flask-APScheduler==1.11.0
RUN mkdir conf logs
COPY conf/cityCode.ini ./conf/cityCode.ini
COPY conf/weather.db ./conf/weather.db
COPY weather_app.pyc ./weather_app.pyc
CMD [ "python3", "./weather_app.pyc" ]
容器编排 Docker-compose.yml
# docker-compose.yml
version: "3"
services:
weather_app:
build: .
image: weather_app
container_name: weather_app
volumes:
- /usr/local/weather/conf/:/usr/src/app/conf
- /usr/local/weather/logs/:/usr/src/app/logs
environment:
WEATHER_API: "http://t.weather.sojson.com/api/weather/city/"
TIME_INTERVAL: 5
ports:
- 5001:5000
restart: always
网友评论