一 数据库的连接
数据库的连接同上下文管理with 一样,需要先开启,再操作,最后关闭
1) 开启连接数据库
import pymysql
conn = pymysql.connect(host='172.25.254.69', user='root',
password='redhat', charset='utf8')
表示连接的是69这台主机,以root的身份,密码为redhat,其中编码格式为utf8
如果你不设置host这项的话,默认连接的是本地的数据库
当然,官方定义了很多的参数,看情况而定你的参数为哪些,上面的为必要参数而已
def __init__(self, host=None, user=None, password="",
database=None, port=0, unix_socket=None,
charset='', sql_mode=None,
read_default_file=None, conv=None, use_unicode=None,
client_flag=0, cursorclass=Cursor, init_command=None,
connect_timeout=10, ssl=None, read_default_group=None,
compress=None, named_pipe=None, no_delay=None,
autocommit=False, db=None, passwd=None, local_infile=False,
max_allowed_packet=16*1024*1024, defer_connect=False,
auth_plugin_map={}, read_timeout=None, write_timeout=None,
bind_address=None, binary_prefix=False)
2) 操作数据库
1> 数据库首先是需要建立一个游标的,来对数据库发送sql语句的
建立游标:
cur = conn.cursor()
2> 对数据库进行增删改查的操作
首先选择需要操作的数据库,这里选择westos作为操作对象
conn.select_db('westos')
这一项连接的时候是可以直接指定的
db="数据库名称"
在数据库westos中,建立一个表myuser
create_sql = 'create table myuser (name varchar(30), age int );'
cur.execute(create_sql)
在表中填入数据
insert_sqli1 = 'insert into myuser VALUES ("user1", 100);'
insert_sqli2 = 'insert into myuser VALUES ("user2", 100);'
cur.execute(insert_sqli1)
cur.execute(insert_sqli2)
删除表中的数据
delete_sqli = 'delete from myuser where name="user2";'
cur.execute(delete_sqli)
实现批量的增删改
users = [('user'+str(i), i) for i in range(100)]
insert_sqli = 'insert into myuser VALUES (%s, %s);'
cur.executemany(insert_sqli, users)
excutemany函数(命令,数组)可以实现批量操作
查看表中的内容
select_sqli = 'select * from myuser;'
res = cur.execute(select_sqli)
print("查看语句的返回结果:", res)
也可以逐条查看表中的内容
print(cur.fetchone())
cur.fetchone类似与文件的操作f.readline, 每次只读取一条记录
也可以查看多条的内容
print(cur.fetchmany(5))
cur.fetchmany, 类似于f.readlines, 返回的是一个元组
显示表的具体描述
desc = cur.description
print("表的描述:",desc )
从表的描述中获取表头
print("表头",[item[0] for item in desc])
当然数据库的查看是需要游标的帮助的
游标的移动,分为(absolute和relative)两种
cur.scroll(0, mode='absolute')
移动游标的位置, 到记录的最开始(绝对移动)
cur.scroll(-10, mode='relative')
移动游标的位置,到当前记录的前10位(相对移动)
最后需要对数据库的操作进行提交
conn.commit()
当然这个也是在你连接的时候就可以解决了autocommit=False,系统默认是关闭的,当
autocommit=True
就可以自动提交了
3) 关闭数据库
但是关闭数据库之前,需要先关掉游标,再去关掉数据库
cur.close()
conn.close()
这就是一系列对数据库的操作流程
二 银行转账操作
要求用数据库实现A给B转账之后,A拥有的金额减小,B拥有的金额增加,若出现意外,转账作废
import pymysql
class TransferMoney(object):
def __init__(self, conn):
self.conn = conn
self.cursor = conn.cursor()
def transfer(self, source_accid, target_accid, money):
"""
转账方法:
# 1. source_accid帐号是否存在;
# 2. target_accid帐号是否存在;
# 3. 是否有足够的钱
# 4. source_accid扣钱
# 5. target_acci加钱
# 6. 提交对数据库的操作
:param source_accid: 源帐号id
:param target_accid: 目标帐号id
:param money: 转账金额
:return: bool
"""
# 判断帐号是否存在
self.check_account_avaiable(source_accid)
self.check_account_avaiable(target_accid)
# 是否有足够的钱
self.has_enough_money(source_accid, money)
try:
# source_accid扣钱
self.reduce_money(source_accid, money)
# print(a)
# target_acci加钱
self.add_money(target_accid, money)
self.conn.commit()
except Exception as e:
# 撤销对于数据库的更改操作, 回滚
self.conn.rollback()
else:
print("%s给%s转账%s成功" % (source_accid, target_accid, money))
def check_account_avaiable(self, accid):
"""判断帐号是否存在, 传递参数为帐号id"""
select_sqli = 'select * from bankData where id=%s' % (accid)
print("execute sql:", select_sqli)
res = self.cursor.execute(select_sqli)
# 判断是否能找到帐号为accid的记录;
if res == 1:
return True
else:
raise Exception("帐号%s不存在" % (accid))
def has_enough_money(self, accid, money):
"""是否有足够的钱"""
select_sqli = 'select money from bankData where id=%s' % (accid)
print('execute sql:', select_sqli)
self.cursor.execute(select_sqli)
# 获取查询到的金钱数额
acc_money = self.cursor.fetchone()[0]
print(acc_money, type(acc_money))
# 判断
if acc_money >= money:
return True
else:
raise Exception("账户%s没有足够的金额, 当前余额为%s" % (accid, acc_money))
def reduce_money(self, accid, money):
# 对于accid减少的金额为money
try:
update_sqli = 'update bankData set money=money-%s where id="%s"' % (money, accid)
print("redcue_money sql:", update_sqli)
self.cursor.execute(update_sqli)
except Exception as e:
print('Error:', e)
def add_money(self, accid, money):
# 对于accid减少的金额为money
try:
update_sqli = 'update bankData set money=money+%s where id="%s"' % (money, accid)
print("add_money sql:", update_sqli)
self.cursor.execute(update_sqli)
except Exception as e:
print('Error:', e)
def __del__(self):
# 当删除对象时, 自动执行, 关闭游标;
self.cursor.close()
if __name__ == '__main__':
conn = pymysql.connect(host='192.168.122.170', user='hello',
password='hello', charset='utf8',
db='westos')
trans = TransferMoney(conn)
trans.transfer('610003', '610002', 100)
三 成绩管理
文件score.dat中保存的是100名学生的姓名和Python课、高数和英语成绩。
1)定义学生类,其中包含姓名、Python课、高数和英语成绩及总分、均分数据成员,成员函数根据需要确定。
2)读入这名学生的成绩,用对象列表进行存储。
3)求出各科和总分的最高分。
4)请按总分的降序(高成绩在前,低成绩在后)排序
5)在屏幕上显示各科及总分的最高分,排序后的成绩单(包括总分)保存到文件odered_score.dat中。
6) 将文件中的所有学生信息, 保存在mariadb数据库中
import random
import pymysql
from itertools import chain
#生成100名学生的成绩
def createdata():
with open('score.dat', 'w') as f:
for i in range(1,101):
name = 'student' + str(i)
python_score = random.randint(60, 100)
math_score = random.randint(60, 100)
english_score = random.randint(60, 100)
f.write(name + '\t' + str(python_score) + '\t' + str(math_score) + '\t' + str(english_score) + '\n')
#建立Student类
class student(object):
def __init__(self, name, python_score, math_score, english_score):
self.name = name
self.python_score = python_score
self.math_score = math_score
self.english_score = english_score
self.sumscore = float(python_score) + float(math_score) + float(english_score)
self.averagescore = self.sumscore / 3
def __repr__(self):
return '姓名:%s python分数:%s 高数分数:%s 英语分数:%s 总分:%s 平均分:%.2f' % (
self.name, self.python_score, self.math_score, self.english_score, self.sumscore, self.averagescore)
def main():
createdata()
#读取 score.dat 文件中的学生成绩,并使用对象列表存储
with open('score.dat') as f:
studentlist = [student(*line.split()) for line in f.readlines()]
#输出各科成绩最高分
print('python最高分:%s' % max(studentlist, key=lambda x: x.python_score).python_score)
print('高数最高分:%s' % max(studentlist, key=lambda x: x.math_score).math_score)
print('英语最高分:%s' % max(studentlist, key=lambda x: x.english_score).english_score)
#对总成绩进行排序,并输出最高分,将排序后的成绩写入文件 odered_score.dat
sumscorelist = sorted(studentlist, key=lambda x: x.sumscore, reverse=True)
print('总分最高:%s' % sumscorelist[0].sumscore)
with open('odered_score.dat', mode='w') as f:
for i in sumscorelist:
print(i)
f.write(str(i) + '\n')
#读取 odered_score.dat 文件, 并将数据写入数据库
with open('odered_score.dat') as f:
conn = pymysql.connect(host='172.25.254.69',user='hello', password='hello', charset='utf8', db='mariadb', autocommit=True)
cur = conn.cursor()
#cur.execute('drop table student;')
newcreate = 'create table student(姓名 varchar(10) not null, python成绩 varchar(5), 高数成绩 varchar(5), 英语成绩 varchar(5), 总分 varchar(5), 平均分 varchar(5));'
cur.execute(newcreate)
for line in f.readlines():
getuseful = [i.split(':') for i in line.split()]
useful = list(chain(*getuseful))[1::2]
linkuse = "insert into student values('%s', '%s', '%s', '%s', '%s', '%s');" % (
useful[0], useful[1], useful[2], useful[3], useful[4], useful[5])
#print(linkuse)
cur.execute(linkuse)
cur.close()
conn.close()
main()
输出显示各科的最高分和总分的最高分
按照总分的高低,从大到小依次排序
数据库中存储的内容和显示的总分排序是相同的