模拟数据流
由于pipelinedb.com在国内的网络不稳定,通过curl命令访问http://pipelinedb.com/data/wiki-pagecounts持续获取数据经常出现超时的状况。并且,随着对PipelineDB理解的加深,单一的数据源结构可能无法满足后续的实践。所以,制作一个简单的脚本,用以模拟不断输入的数据流。
系统环境:Windows 7
脚本语言:Python
安装Psycopg2适配器
简介
模拟数据流的写入,需要访问PostgreSQL数据库,作为Python编写中最受欢迎的PostgreSQL数据库适配器,Psycopg2是首选。它完整实现了Python DB API 2.0规范和线程安全(多线程共享连接),它可以创建或销毁大量游标,并生成大量并发的INSERT或UPDATE。
Psycopg2主要采用C语言封装libpq,既高效又安全。它具备异步通信、通知以及支持COPY TO/COPY FROM等特性。同时,支持大量的Python类型,并能匹配PostgreSQL的数据类型。鉴于灵活的对象适应能力,Psycopg2更便于扩展和定制。
安装过程
下载Windows版Psycopg2,当前最新版本为2.8.6。
https://pypi.org/project/psycopg2/2.8.6/#files
选择amd64版本,其中cp27表示支持Python版本为2.7,同理,cp39表示支持Python 3.9版本。
psycopg2-2.8.6-cp27-cp27m-win_amd64.whl (1.1 MB) Wheel cp27 Sep 7, 2020
如果运行Python脚本的环境尚未安装Pip,则需要提前安装部署,当前最新的发布版本为20.2.4。(另,关于Python版本,笔者使用的是2.7,Python的安装不再累述。)
https://pypi.org/project/pip/#files
选择tar.gz包,下载。
pip-20.2.4.tar.gz (1.5 MB) Source None Oct 18, 2020
解压,并进入解压后文件夹,打开控制台CMD,执行命令:
python setup.py install
出现下方提示,则说明Pip安装成功:
Finished processing dependencies for pip==20.2.4
若提示ImportError: No module named setuptools异常,则还安装setuptools,下载途径如下:
https://pypi.org/project/setuptools/#files
同样使用python setup.py install进行安装。
Pip安装完成后,需要将pip的路径添加到环境变量中。进入Python 2.7安装目录下的Scripts文件夹,如,笔者的路径为:
C:\Python27\Scripts
右击计算机,选择属性 - 高级系统设置 - 环境变量,选择系统变量中Path,编辑,将上述路径添加至变量值中。
进入psycopg2-2.8.6-cp27-cp27m-win_amd64.whl所在路径,打开控制台CMD,执行命令:
pip install psycopg2-2.7.4-cp33-cp33m-win_amd64.whl install
出现下方提示,则说明Psycopg2安装成功:
Successfully installed psycopg2-2.8.6
问题及解决方案
问题一
描述:在安装Setuptools过程中,提示错误信息
RuntimeError: Python 2.7 or later is required
原因:Setuptools支持的Python版本有限,本机上Python版本太低,或者不匹配。
解决方法:安装并使用更高或对应版本的Python。
问题二
描述:在安装Psycopg2过程中,提示错误信息
Error: Unable to find vcvarsall.bat
原因:本机安装的Python的版本和Visual C++ 版本不兼容,导致编译不成功。
解决方法:保证Python的版本Visual Studio的版本正确对应。
Python | Visual C++ | Visual Studio |
---|---|---|
Python 2.6 / 2.7 / 3.0 / 3.1 / 3.2 | Visual C++ 9.0 | Visual Studio 2008 |
Python 3.3 / 3.4 | Visual C++ 10.0 | Visual Studio 2010 |
Python 3.5 / 3.6 / 3.7 | Visual C++ 14.0 | Visual Studio 2015 |
Python 3.8 / 3.9 | Visual C++ 15.0 | Visual Studio 2017 |
编写数据流模拟脚本
Psycopg2方法说明
打开一个连接访问PostgreSQL数据库。如果成功打开数据库时,它返回一个连接对象:
psycopg2.connect(database = "db", user = "postgres", password = "postgres", host="127.0.0.1", port = "5432")
创建一个光标,以此为数据库的访问对象:
connection.cursor()
执行SQL语句:
cursor.execute(sql [, optional parameters])
Psycopg2的模块支持占位符用%s标志,即,接受可被参数化的SQL语句(占位符,而不是SQL文字)。例如:
cursor.execute(“INSERT INTO tab_1 VALUES (%s, %s)”, (var_1, var_2))
返回数据库中,最后的execute()所插入、删除或修改的行的总数:
cursor.rowcount
提交当前事务:
connection.commit()
如果不调用这个方法,无论之前做了什么修改,自前一次调用commit()起的数据,对于其他数据库连接是不可见的。
回滚当前事务:
connection.rollback()
关闭数据库连接:
connection.close()
Note:该方法不会自动调用commit(),只是关闭数据库连接而不调用commit()方法,那么之前所有更改将会丢失。
更多方法的详细使用说明,请访问Psycopg官网进行了解:
https://www.psycopg.org/docs/
模拟数据流
Python脚本用以实现下列功能:
I. 循环写入已创建的流,数据间隔时长为5秒;
II. 流数据内容随机生成,其中,project列为固定范围内容,hour列为指定时间范围内随机值,title / view_count / size列为随机字符串或整型;
III. 避免每次INSERT操作之前申请连接,之后释放连接,使用单一连接,并在循环结束后释放。
完整代码如下所示:
# coding: utf-8
# 导入psycopg2包
import psycopg2
import time
import random
import string
import sys
# 数据库连接信息
PG_SQL_LOCAL = {
'database': 'postgres',
'user': 'postgres',
'password': "Abc12345",
'host': '192.168.236.11',
'port': '5432'
}
# 生成指定范围内的随机时间
def RandomTime():
# 设置开始日期时间元组(2020-01-01 00:00:00)
dts_start = (2020, 1, 1, 0, 0, 0, 0, 0, 0)
# 设置结束日期时间元组(2020-12-31 23:59:59)
dts_end = (2020, 12, 31, 23, 59, 59, 0, 0, 0)
# 生成开始时间戳
start_time = time.mktime(dts_start)
# 生成结束时间戳
end_time = time.mktime(dts_end)
# 在开始和结束时间戳中随机取出一个
t_pick = random.randint(start_time, end_time)
# 将时间戳生成时间元组
date_touple = time.localtime(t_pick)
# 将时间元组转成格式化字符串(1976-05-21)
rand_datetime = time.strftime("%Y-%m-%d %H:%M:%S", date_touple)
return rand_datetime
# 数据库操作类
class PGStreamOperate:
# 初始化类成员
def __init__(self):
self.hour_py = ""
self.project_py = ""
self.title_py = ""
self.view_count_py = 0
self.size_py = 0
self.conn = None
# 生成随机值
def RandValue(self):
self.hour_py = time.strftime("%Y-%m-%d %H:00:00", RandomTime())
self.project_py = random.choice([u"A-Obj", u"B-Obj", u"C-Obj", u"D-Obj", u"E-Obj"])
self.title_py = ''.join(random.sample(string.ascii_letters + string.digits, 10))
self.view_count_py = random.randint(1, 50)
self.size_py = random.randint(100, 10000)
# 连接数据库
def Connect(self):
self.conn = psycopg2.connect(**PG_SQL_LOCAL)
print('Connect Successful !')
# 释放连接
def DisConnect(self):
self.conn.close()
print('DisConnect Successful !')
# 插入流数据
def Insert(self):
self.project_py = self.project_py.decode("utf-8")
sql_statement = "INSERT INTO wiki_stream (hour, project, title, view_count, size) values ('%s', '%s', '%s', %d, %d);" % (self.hour_py, self.project_py, self.title_py, self.view_count_py, self.size_py)
self.cursor = self.conn.cursor()
self.cursor.execute(sql_statement)
self.conn.commit()
#######################################################
#
# Main
#
#######################################################
reload(sys)
sys.setdefaultencoding("utf-8")
exec_degree = 1
dal = PGStreamOperate()
dal.Connect()
# 间隔5秒循环插入流
while (exec_degree <= 10000):
dal.RandValue()
dal.Insert()
print('Insert wiki_stream, No.%d' % exec_degree)
exec_degree = exec_degree + 1
time.sleep(5)
dal.DisConnect()
运行该脚本,上一节中创建的流wiki_stream,将会持续不断的得到数据输入。相应的,以上脚本稍作调整,即可满足其他不同结构流的数据输入。