Python工具箱系列(三十三)

Posted shanxihualu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python工具箱系列(三十三)相关的知识,希望对你有一定的参考价值。

在物联网时代,出现了大量以时间为中心海量产生的传感器数据,称为时序数据。

Timescaledb

在物联网时代,出现了大量以时间为中心海量产生的传感器数据,称为时序数据。这类数据的特点是:

  • 数据记录总有一个时间戳。

  • 数据几乎总是追加,不更新也不删除。

  • 大量使用近期的数据。很少更新或者回填时间间隔的缺失数据。

  • 与时间间隔频率关系不大。但累积的数据量大,可能会有峰值。

  • 对这类数据有多种聚合查询的需求,并且越快越好。例如,截止到目前为止,最大值/最小值/平均值是多少,数据流速是多少等。

为此,IT界兴起了时序数据库。TimeScaleDB是其中的佼佼者,截止到2022年7月,它的排名在第5名,值得使用。由于TimeScaleDB是postgresql的一个插件,因此非常便于安装与使用。同时,它也是一个开源的时间序列数据库,为快速获取和复杂查询进行了优化。此外,它也是多模型设计,在体现与时序数据相关的特性外,它执行的是“完整的SQL”,程序员很容易使用与管理它。

它的安装不复杂。使用以下命令在ubuntu bionic下安装单机版本。

apt install -y gnupg postgresql-common apt-transport-https lsb-release wget
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
echo "deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main" > /etc/apt/sources.list.d/timescaledb.list
wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | apt-key add -
apt update
apt install -y timescaledb-2-postgresql-14
# 做一个调整
timescaledb-tune --quiet --yes
# 重新启动数据库服务
systemctl restart postgresql

# 以postgres用户启动命令行
su postgres -c psql

# 在psql命令行环境中。输入以下命令,从而关联到timescaledb这个扩展上。
CREATE database sensordb;
\\c sensordb
CREATE EXTENSION IF NOT EXISTS timescaledb;
\\q

# 再次连接
su postgres -c \'psql -d sensordb\'
# 显示扩展列表(extensions)
\\dx

一、创建时序相关得表

在sensordb下创建测试用的表,这个创建的过程有些特殊。相关命令如下:

 

# 传感器表,传统的表
CREATE TABLE sensors(
  id SERIAL PRIMARY KEY,
  type VARCHAR(50),
  location VARCHAR(50)
);

# 传感器数据库,这个将转换成为超表
CREATE TABLE sensor_data (
  time TIMESTAMP NOT NULL,
  sensor_id INTEGER,
  pm25 DOUBLE PRECISION,
  temperature DOUBLE PRECISION,
  FOREIGN KEY (sensor_id) REFERENCES sensors (id)
);

# CREATE EXTENSION IF NOT EXISTS timescaledb;

# 转换为超表
SELECT create_hypertable(\'sensor_data\', \'time\');

# 生成4个传感器
INSERT INTO sensors (type, location) VALUES
(\'a\',\'地板\'),
(\'a\', \'天花板\'),
(\'b\',\'地板\'),
(\'b\', \'天花板\');

# 测试一下。
select * from sensors;

 

接下来,使用python连接时序数据库,并且模拟相关的数据插入到表中。

二、使用Python模拟数据

 

import psycopg2
import random
import datetime

# 事先创建后数据库demodb
demodb = psycopg2.connect(database="sensordb", user="postgres",
                          password="88488848", host="172.17.2.151", port="5432")

democur = demodb.cursor()

currenttime = datetime.datetime.now()

# 插入模拟出来的数据。
for _ in range(100000):
    currenttime = currenttime+datetime.timedelta(seconds=1)
    for id in range(1,5,1):
        pm25 = random.uniform(0, 300)
        temp = random.uniform(0, 40)
        insertsql = f\'\'\'insert into sensor_data(sensor_id,pm25,temperature,time) values(id,pm25,temp,\'currenttime\')\'\'\'
        democur.execute(insertsql)
    demodb.commit()

democur.close()
demodb.close()

 

这里插入10万秒的数据,相当于100000/86400=1.15(天)的数据。在插入数据的同时,就可以同时在数据库中进行按30分钟的分桶查询,这是时序数据库的一个特殊功能。

# su postgres -c \'psql -d sensordb\'

SELECT
  time_bucket(\'30 minutes\', time) AS period,
  AVG(temperature) AS avg_temp,
  last(temperature, time) AS last_temp,
  AVG(pm25) AS avg_pm25
FROM sensor_data
GROUP BY period;

SELECT
  time_bucket(\'60 minutes\', time) AS period,
  AVG(temperature) AS avg_temp,
  last(temperature, time) AS last_temp,
  AVG(pm25) AS avg_pm25
FROM sensor_data
GROUP BY period;

此时,按30分钟时间窗口聚会的数据查询效果如下图所示:

可以看出,TimeScaleDB已经将数据按30分钟来聚合分析。当然,改成任意时间也是可以的,例如,可以改成5秒分析一次也可以,生成结果的时间也非常快。

 

我的第三十三篇博客---flask

使用框架的优点:
稳定性和可扩展性强
可以降低开发难度,提高了开发效率

在Python中常用的Web框架有:
flask
django
tornado

Flask诞生于2010年,是Armin ronacher用Python语言基于Werkzeug工具箱编写的轻量级Web开发框架
Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQL_Alchemy),都需要用第三方的扩展来实现。
其WSGI工具箱采用Werkzeug(路由模块),模块引擎则使用Jinja2.这两个也是Flask框架的核心

Flask常用扩展包:
Flask-SQLalchemy:操作数据库
Flask-script:插入脚本
Flask-migrate:管理迁移数据库
Flask-Session:Session存储方式指定
Flask-WTF:表单
Flask-Mail:邮件
Flask-Bable:提供国际化和本地化支持,翻译;
Flask-Login:认证用户状态;
Flask-OpenID:认证;
Flask-RESTful:开发REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和时间;
Flask-Admin:简单而可扩展的管理接口的框架

扩展列表:http://flask.pocoo.org/extensions/

1.中文文档(http://docs.jinkan.org/docs/flask/)
2.英文文档(http://flask.pocoo.org/docs/0.11/)

 

基本格式:
from flask import Flask
app=Flask(__name__)
@app.route(‘/‘)
def a():
return ‘aa‘
app.run()

打开谷歌 网址为你的ip地址后加上:再加上默认的端口号5000 页面展示为aa

app.run(host=‘0.0.0.0‘,port=80,debug=True)
host:设置为‘0.0.0.0‘时在同一个局域网别的电脑ip都能访问,不设置这个参数时只有自己的ip能访问
port:是默认端口号,为80时,网址后面不用加:你设置的端口号,
debug:在代码中修改return的值后debug的值为True时,不用重新执行程序,刷新网页即可刷新内容

拓展:
from flask import Flask
app=Flask(__name__)
@app.route(‘/<orders_id>‘) #加个<> <>里写的内容为参数
def a(orders_id):
return ‘%s‘%orders_id
app.run()
在谷歌里输入你的ip后加上/你要写的内容 网页展示内容即为你要写的内容
如果限制只能是数字的话 <int:orders_id> <float:orders_id>

 

return 只能返回字符串 和render_template
如果要返回字典之类的 要转成json类型
import json
json.dumps()

from flask import Flask,jsonify

return {‘a‘:‘b‘} 报错
return str({‘a‘:‘b‘}) 纯文本形式,没有数据类型,即没有键值对
return json.dumps({‘a‘:‘v‘}) 文本形式,但保留了键值对
return jsonify({‘a‘:‘v‘}) json类型 有键值对

app.conifg[‘JSON_AS_ASCII‘]=False #将返回的汉字不以ASCII形式返回

app.config.from_pyfile(‘settings.ini‘) 可以新建settings.ini 在这里写配置

 

 重定向

from flask import Flask,redirect,url_for
app=Flask(__name__)
@app.route(‘/‘)
def a():
return ‘a‘

@app.route(‘/five‘)
def five():
return redirect(url_for(‘a‘)) #当你输入网址为你的ip+/+five 时 这个网页展示内容其实就跳转到a()方法里返回的内容
____________________________________________________________________________
重定向到黑马官网
@app.route(‘/demo5‘)
def demo5():
return redirect(‘http://www.itheima.com‘)
____________________________________________________________________________
重定向到自己写的视图函数
可以直接填写自己url路径
也可以使用url_for生成指定视图函数所对应的url

@app.route(‘/demo1‘)
def demo1():
return ‘demo1‘

#重定向
@app.route(‘/demo5‘)
def demo5():
return redirect(url_for(‘demo1‘))
____________________________________________________________________________
重定向到带有参数的视图函数

在 url_for 函数中传入参数

# 路由传递参数
@app.route(‘/user/<int:user_id>‘)
def user_info(user_id):
return ‘hello %d‘ % user_id

# 重定向
@app.route(‘/demo5‘)
def demo5():
# 使用 url_for 生成指定视图函数所对应的 url
return redirect(url_for(‘user_info‘, user_id=100))

 

取网址参数:

 

from flask import Flask,request,jsonify
app=Flask(__name__)
@app.route(‘/<id>‘)
def a(id):
return ‘%s‘%id

当你输入的网址为你的ip + / + 你要展现的内容, 页面内容即为你要展现的内容

@app.route(‘/‘)
def b():
name=request.args.get(‘name‘)
id=request.args.get(‘id‘)
return jsonify({‘name‘:name,‘id‘:id})

当你输入的网址为你的ip + /? +name=小明&id=7 展现的内容即为{‘name‘:小明,‘id‘:7}

 

指定文本类型:

json类型: ‘content-type‘:‘application/json‘
字符串类型:‘content-type‘:‘text/plain‘
解析类型:‘content-type‘:‘text/html‘

 

route:

指定路由地址
#指定访问路径为demo1
@app.route(‘/demo‘)
def demo1():
return ‘demo1‘

给路由传参
有时我们需要将同一类URL映射到同一个视图函数处理,比如:使用同一个视图函数来显示不同用户的个人信息

#路由传递参数
@app.route(‘/user/<user_id>‘)
def user_info(user_id):
return ‘hello %s‘%user_id

输入的网址后缀加的什么 在网页展示的就是什么,下面那个函数括号里必须是上面的参数
路由传递的参数默认当作string处理,也可以指定参数的类型

#路由传递参数
@app.route(‘user/<int:user_id>‘)
def user_info(user_id):
return ‘hello %d‘%user_id

这里指定int,尖括号中的内容是动态的。在此暂时可以理解为接受int类型的值,实际上int代表使用IntergeConverter去处理url传入的参数

指定请求方式
在Flask中。定义一个路由,默认的请求方式为:
GET
OPTIONS(自带)
HEAD (自带)

如果像添加请求方式,
@app.route(‘/demo2‘,methods=[‘GET‘,‘POST‘])
def demo2():
#直接从请求中取到请求方式并返回
return request.method

 

request属性:

request就是flask中代表当前请求的request对象,期中一个请求上下文变量(理解成全局变量,在视图函数中直接使用可以取到当前本次请求)
属性 说明 类型
data 记录请求的数据,并转换为字符串 *
form 记录请求中的表单数据 MultiDict
args 记录请求中的查询参数 MultiDict
cookies 记录请求中的cookie信息 Dict
headers 记录请求中的报文头 EnvironHeaders
method 记录请求使用的HTTP方法 GET/POST
url 记录请求的URL地址 string
files 记录请求上传的文件 *

Request.Form:获取以POST方式提交的数据(接收Form提交来的数据);
Request.QueryString:获取地址栏参数(以GET方式提交的数据)
Request:包含以上两种方式(优先获取GET方式提交的数据),它会在QueryString、Form、ServerVariable中都搜寻一遍。

requests模块发送请求有data、params两种携带参数的方法。

params在get请求中使用,data在post请求中使用。params是往url后面添加参数,data是指POST请求传入的字典或对象

 

以上是关于Python工具箱系列(三十三)的主要内容,如果未能解决你的问题,请参考以下文章

python第三十三天----静态方法类方法属性方法

Swift系列三十三 - 面向协议编程

Swift系列三十三 - 面向协议编程

Springboot系列(三十三):Springboot如何手动连接库并获取指定表结构|超级详细,建议收藏

Python工具箱系列(三十四)

Powershell管理系列(三十三)PowerShell操作之查询AD账号对应的OU存放位置