mysql模块
(import mysql.connector
)
安装驱动:pip install mysql-connector
实例
import mysql.connector
conn = mysql.connector.connect(user='root', password='123456', database='test') #连接数据库
cursor = conn.cursor()
#相当于建立一个接口,以后就往这里面输入数据库语句进行操作
cursor.execute('select * from user')
#执行sql查询语句,但注意这里查询的结果必须要取走以后才能再次进行操作(包括增删改),即下面那一句得执行
values = cursor.fetchall()
print(values)
#此时就返回查询结果,是一个列表,每行内容单独用元组保存,比如:[('a', 'v', 'c'), ('aaa', '111', 'dawson')]
cursor.execute('create table userd (id varchar(20) primary key, name varchar(20))') #新建表
cursor.close() #结束后关闭数据库连接,返回True说明关闭成功
pymysql模块
(自带模块)
使用方式:(按执行顺序)
(1)创建连接
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="123456", db="test")
(2)创建游标
(即操作对象)
cursor = conn.cursor()
(3)设置类型
默认游标是元组类型,可以设置为别的,这里游标设置为字典类型(可选):
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
(4)执行SQL
effect_row = cursor.execute("select * from user") #会返回收影响行数
(5)获取数据
row_1 = cursor.fetchone() #获取剩余结果的第一行数据
row_2 = cursor.fetchmany(3) # 获取剩余结果前n行数据
row_3 = cursor.fetchall() # 获取剩余结果所有数据
(6)控制位置移动
因为读取/操作数据后游标位置会变,比如取了第一行数据,剩下能看的数据就只有第二行以后的了,所以需要控制位置移动:
cursor.scroll(1,mode='relative')
#相对当前位置移动,比如1就是跳过一条,-1就是回到上一条
cursor.scroll(2,mode='absolute')
#相对绝对位置移动,比如0就是回到第一条,但不能通过-1到最后一条,通过查看源码可以得知范围为0-length
(7)提交操作
一个操作结束后需要进行提交,不然无法保存新建或者修改的数据等新的操作:
conn.commit()
(8)关闭游标
cursor.close()
(9)关闭连接
conn.close()
(10)数据回滚(可选)
db.rollback()
完整示例
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='test') #建立连接
cursor = conn.cursor() #创建游标
effect_row = cursor.execute("select * from userd") #会返回收影响行数
print(effect_row) #这里收到3条数据
result = cursor.fetchall() #获取所有数据
print("result:", result)
result2 = cursor.fetchall() #游标此时在最后,所以内容为空
print("result2:", result2)
cursor.scroll(-1,mode='relative') #跳回上一条,这里就是最后一条
result3 = cursor.fetchall()
print("result3:", result3)
cursor.scroll(0,mode='absolute') #跳回第一条
result4 = cursor.fetchall()
print("result4:", result4)
conn.commit() #结束时提交、关闭三连发
cursor.close()
conn.close()
结果:
3
result: (('1', 'a'), ('2', 'b'), ('3', 'c'))
result2: ()
result3: (('3', 'c'),)
result4: (('1', 'a'), ('2', 'b'), ('3', 'c'))
更多参考
https://www.cnblogs.com/wt11/p/6141225.html
Mongodb
(基于分布式的非关系型数据库,即没有固定表结构,可以通过键值对方式存储数据,而不是像mysql那种关系型数据库一样有固定的表结构,只能按规定的来存数据,可以去官网下载安装)
关系型数据库和非关系型数据库区别可参考:https://blog.csdn.net/qq_31536117/article/details/78179646
安装配置
可参考:https://blog.csdn.net/winstonlau/article/details/79439223
配置数据库存储路径:
创建好数据库文件夹后,命令行输入:mongod --dbpath 文件夹路径
进入客户端:
在命令行输入mongo
(配好path路径以后),就会进入mongo的shell
配置环境:
打开管理员权限命令行,定位到mongodb
的bin
目录下,输入:
mongod __bind__ip 0.0.0.0 --logpath E:\Mongodb\Server\4.0\log\mongod.log --logappend --dbpath E:\Mongodb\Server\4.0\data\db --port 27017 --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install
上面意思依次是绑定ip、log文件路径、数据库路径、端口、服务器名称
可视化工具:
下载Robomongo
python相关操作模块:
pip install pymongo
操作示例
import pymongo
>>> client = pymongo.MongoClient('localhost') #建立一个连接
# client = pymongo.MongoClient('localhost', username="admin", password="123456")
# 需要密码的连接方式
>>> db = client['newtestdb'] #创建一个数据库newtestdb
>>> db['table'].insert({'name':'aaa'}) #创建一个数据库表table,并插入一个字典
>>> db['table'].find_one() #查找一条数据
{'_id': ObjectId('5b3d76daab406029e01944f6'), 'name': 'aaa'}
>>> db['table'].find_one({'name':'aaa'}) #查找指定数据
{'_id': ObjectId('5b3d76daab406029e01944f6'), 'name': 'aaa'}
更多pymongo操作参考
https://www.cnblogs.com/nixingguo/p/7260604.html
事务使用
需要mongodb版本4.0+,并且配置副本集才能够使用事务机制
事务配置参考:https://www.jianshu.com/p/117b43f88769
pymongo事务操作参考:https://www.cnblogs.com/82nlf-xlqb/p/11771530.html
事务封装
事务环境配置完成以后,还需要在指定session当中执行,示例如下:
import pymongo
client = pymongo.MongoClient('localhost', 27017)
session = client.start_session()
col = client["test"]["aaa"]
# 事务开始
session.start_transaction()
try:
col.insert_one({"world":1}, session=session)
raise
col.insert_one({"hello":1}, session=session)
except Exception as e:
session.abort_transaction()
else:
session.commit_transaction()
finally:
session.end_session()
可以看出事务的代码当中需要开启事务,并且所有相关的事务语句还要指定session
执行,语法过于繁琐。因此我们可以结合with
管理和装饰器进行封装如下:
import pymongo
config = {
"host": "localhost",
"port": 27017,
}
client = pymongo.MongoClient(**config)
class MongoOperatorDeco(object):
"""
pymongo事务操作封装类,传入操作的对象和session,自动添加session事务操作
"""
def __init__(self, o, session):
self.o = o
self.session = session
def __getattr__(self, name):
attr = self.o.__getattribute__(name)
return self.mongo_session_deco(attr)
def mongo_session_deco(self, func):
"""
装饰器封装,添加事务操作参数
"""
def mongo_session_deco_fun(*arg, transaction=True, **args):
if transaction:
args["session"] = self.session
return func(*arg, **args)
return mongo_session_deco_fun
class MongoSessionContext(object):
"""
pymongo事务context管理器,通过with语句简单管理session事务操作
"""
def __init__(self):
super().__init__()
def __enter__(self):
"""
进入context,返回当前事务session
"""
self.session = client.start_session()
self.session.start_transaction()
return self.session
def __exit__(self, exc_type, exc_value, traceback):
"""
context内顺序执行完毕后将提交事务,若抛出异常则进行回滚,最终关闭session
"""
if not exc_type:
self.session.commit_transaction()
else:
self.session.abort_transaction()
self.session.end_session()
if __name__ == "__main__":
with MongoSessionContext() as session:
# 在封装的context中执行事务语句
col = MongoOperatorDeco(client["test"]["aaa"], session)
# 通过装饰器包装当前操作对象,操作时自动添加session
col.insert_one({"world":1})
col.insert_one({"world":2}, transaction=False)
# 这句不参与事务,因此不论后面语句是否出错,都会执行成功
col.insert_one({"world":3})
# raise
# 报错,参与事务的语句都不会执行成功
可以看出经过封装以后,事务代码就和之前编写的操作语句类似了
mongodbengine
该模块封装了对mongodb的ORM操作,举例:
from mongoengine import *
class Company(Document):
'''公司表,有公司名和规模属性'''
choice = (('s', 'small'),
('m', 'middle'),
('l', 'large'))
name = StringField(max_length=50, required=True)
size = StringField(choices=choice, required=True)
class Work(EmbeddedDocument):
'''工作嵌入表,和普通的表不太一样,其不会作为一个表单独存在,而是嵌入在别的表内部,有工作名称和薪资'''
name = StringField(max_length=50, required=True)
salary = FloatField(required=True)
class People(Document):
'''个人信息表'''
choice = (('F', 'female'),
('M', 'male'),)
name = StringField(max_length=100, required=True, unique=True)
age = IntField(required=True)
gender = StringField(choices=choice, required=True)
work = ListField(EmbeddedDocumentField(Work), required=True)
# 一个人可以身兼多职,而多个职位存放在一个list里,list当中每个工作是一个嵌入字段,即list里存放的是一堆对象
company = ReferenceField(Company, required=True)
# 引用字段,存放的是在Company表里对应的唯一id
note = DictField(required=True)
# 跟EmbeddedDocumentField差不多,但是DictField没有定义结构,因此字段没有限制
if __name__ == '__main__':
connect(db='test', host='localhost', port=27017)
# connect(db='test', host='localhost', port=27017, username="admin", password="123456", authentication_source='admin')
# 需要密码的验证方式
company_a = Company(name='middle company', size='m')
company_a.save()
# 因为是单独存表,如果引用字段要引用时,必须是表里存在的数据,所以这里需要先保存
work_a = Work(name='w-a', salary=10000)
work_b = Work(name='w-b', salary=5000)
work_c = Work(name='w-c', salary=3000)
# 因为是嵌入表,直接在嵌入的表里再存即可
note_a = {"describe": "...", "other": "nothing"}
people_a = People(name='aaa', age=30, gender='M', company=company_a ,work=[work_a, work_b, work_c], note=note_a)
people_a.save()
# 查询数据,在数据库可以看到在People表和Company表里添加了数据
# 但并没有新建一个Work表,Work的数据在People的一个字段当中
result = People.objects.filter(name='aaa').first()
for work in result.work:
print(work.name, work.salary)
print(result.company.name)
print(result.to_mongo())
# 内容转字典格式,后面还能调用to_dict()方法转成字典类型
更多使用参考:
https://www.cnblogs.com/wefeng/p/11503102.html
https://www.jb51.net/article/64861.htm
注:
orm效率问题参考:http://xiaorui.cc/archives/2048
mongdbengine序列化/反序列化-marshmallow_mongoengine
该模块需要基于版本小于3的marshmallow,安装命令:
pip install marshmallow==2.13.6 marshmallow_mongoengine
代码示例:
from mongoengine import *
from marshmallow_mongoengine import ModelSchema, fields
# ---------------------------------
# 定义模型
class Company(Document):
name = StringField(max_length=50, required=True)
size = StringField(required=True)
def __str__(self):
return str({"name": self.name, "size": self.size})
class Work(EmbeddedDocument):
name = StringField(max_length=50, required=True)
salary = FloatField(required=True)
class People(Document):
name = StringField(max_length=100, required=True, unique=True)
age = IntField(required=True)
gender = StringField(required=True)
work = ListField(EmbeddedDocumentField(Work), required=True)
company = ReferenceField(Company, required=True)
# ---------------------------------
# 定义序列化类
class CompanySchema(ModelSchema):
name = fields.String()
# 定义序列化的字段,不定义默认序列化全部字段
class Meta:
model = Company
# 绑定model
class PeopleSchema(ModelSchema):
company = fields.Nested(CompanySchema)
# 对于引用字段使用Nested,否则序列化后只是一个objectId而不是完整的数据
class Meta:
model = People
if __name__ == "__main__":
connect(db='test', host='localhost', port=27017)
di_work = {"name": "engineer", "salary": 10000}
di_company = {"name": "xxx", "size": "big"}
unseries_company = CompanySchema().load(di_company).data
# 反序列化成对象
unseries_company.save()
print(unseries_company)
series_company = CompanySchema().dump(unseries_company).data
# 序列化成字典
di_people = {"name": "aaa", "age": 10, "gender": "male", "work": [di_work], "company": series_company}
# di_people = {"name": "aaa", "age": 10, "gender": "male", "work": di_work, "company": unseries_company.id}
# 如果没有使用Nested字段,则直接传入指定对象的objectId
unseries_people = PeopleSchema().load(di_people).data
# people反序列化
unseries_people.save()
series_people = PeopleSchema().dump(unseries_people).data
# 序列化成字典
print(series_people)
参考:https://blog.csdn.net/qq_41637554/article/details/82464186
https://blog.csdn.net/weixin_42042680/article/details/90206632
Redis
(也是一种非关系型数据库,通过键值对存数据,由于其特殊的功能,常用于分布式存储当中)
基本配置
下载地址:
https://github.com/MicrosoftArchive/redis/releases
可视化工具下载:
https://github.com/uglide/RedisDesktopManager/releases?after=0.9.0-alpha5
python相关操作模块:
pip install redis
操作示例
import redis
>>> r = redis.Redis('localhost', 6379) #连接数据库
String操作:
>>> r.set('name', 'aaa') #set插入单个数据
True
>>> r.get('name') #get获取单个数据
b'aaa'
>>> user = {'name':'dawson','pwd':'111'}
>>> r.mset(user) #mset插入多个键值对
True
>>> r.mget(user) #mget获取多个键值对,里面参数可以是列表、字典等
[b'111', b'dawson']
>>> r.mget('name','pwd')
[b'dawson', b'111']
>>> r.append('name', 'sad') #append往后面添加字符
9
>>> r.get('name')
b'dawsonsad'
>>> r.delete('name') #delete删除
1
>>> r.mget(user)
[b'111', None]
List操作:
>>> r.lpush('keyn', 'a', 'b', 'c') #lpush从左插入数据
3
>>> r.rpush('keyn', 'd', 'e') #rpush从右插入数据
5
>>> r.lrange('keyn', 0, -1) #lrange获取某个数据,从第0个到最后一个
[b'c', b'b', b'a', b'd', b'e']
>>> r.lpop('keyn') #lpop弹出最左边数据,rpop弹出最右
b'c'
Set操作:
>>> sets = ['a', 'b', 'c']
>>> r.sadd('set1', *sets)
#sadd插入到集合(不会重复),如果不加*,会将整个['a', 'b', 'c']传入
#即只有一个数据,加*就是分别传'a', 'b', 'c'三个数据,srem删除
3
>>> r.smembers('set1') #smembers获取集合数据
{b'a', b'b', b'c'}
>>> r.sadd('set2', *['a', 1, 2])
3
>>> r.sadd('set3', *['a', 3, 'b'])
3
>>> r.sinter('set1', 'set2', 'set3') #sinter返回几个集合之间的交集
{b'a'}
>>> r.sunion('set1', 'set2', 'set3') #sunion返回几个集合之间的并集
{b'3', b'a', b'b', b'c', b'2', b'1'}
>>> r.sismember('set1', 'a') #sismember判断是否是集合元素
True
>>> r.sismember('set1', 'h')
False
Hash操作:
>>> r.hset('news', 'title', 'one') #hset添加数据,这里给news的title赋值one
1
>>> r.hset('news', 'content', 'two') #这里给news的content赋值two
1
>>> r.hget('news', 'title') #hget获取数据,hdel删除
b'one'
>>> r.hmget('news', 'title', 'content') #hmget获取多个数据,hmset设置多个
[b'one', b'two']
>>> r.hkeys('news') #hkeys获取所有键
[b'title', b'content']
>>> r.hvals('news') #hvals获取所有值
[b'one', b'two']
其他
windows下添加redis服务
输入以下命令:
redis-server --service-install redis.windows.conf --loglevel verbose