美文网首页
Python 高级 第四课(未完成。。)

Python 高级 第四课(未完成。。)

作者: 小小小小饼 | 来源:发表于2018-04-16 17:14 被阅读23次

同样还是学习@斌叔的程序媛课程的笔记~

第四课

本次运用本课程的Socket和sqlite3 改一下这个程序,通过socket将日记保存至数据库中:
整体流程如下图:


Screen Shot 2018-04-11 at 4.46.56 PM.png.png

client.py 是客户端
server.py 是服务端
database.py 是数据库模块
diary.py 是中级课程中的日记本

首先从数据库开始,把它们抽象成一个类,作为一个模块,方便使用

showAllData 用于展示数据,可以在调试的时候使用,方便我们看到结果是否正确

getDataDict 用于获取数据,并将数据拼成字典形式返还给客户端

sqlite.py
import sqlite3

class DB(object):
    """docstring for DB"""
    def __init__(self):
        super(DB, self).__init__()
        self.connect = sqlite3.connect("test.db")
        self.cursor = self.connect.cursor()

    def searchTable(self,tableName):
        flag = False
        self.cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table' ")
        for item in self.cursor.fetchall():
            if item[0] == tableName:
                flag = True
                break
        return flag

    def initTable(self,tableName):
        if self.searchTable(tableName) == False:
            sql = "CREATE TABLE " + tableName + "(id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT , content TEXT)"
            self.cursor.execute(sql)
            print(u"创建表成功")
        else:
            print(u"该表已存在")

    def insertData(self, tableName, data):
        sql = "INSERT INTO " + tableName + "(title, content) VALUES (?, ?)"
        self.cursor.execute(sql,data)
        self.connect.commit()
        return "保存成功"

    def deletaData(self, tableName, id):
        sql = "DELETE FROM " + tableName + " WHERE id = " + str(id)
        self.cursor.execute(sql)
        self.connect.commit()
        return "删除成功"

    def updateData(self, tableName,id,data):
        sql = "UPDATE " + tableName + " SET title = '" + data[0] + "', content = '" + data[1] + "' Where id = " + str(id)
        self.cursor.execute(sql)
        self.connect.commit()
        return "修改成功"

    def searchData(self, tableName, id):
        sql =  "SELECT * FROM " + tableName + " WHERE id = " + str(id)
        self.cursor.execute(sql)
        tup = self.cursor.fetchone()
        dict = {'title': tup[1], 'content': tup[2]}
        return str(dict)

    def showAllData(self, tableName):
        sql = "SELECT * FROM " + tableName
        for row in self.cursor.execute(sql):
            print(row)

    def getDataDict(self, tableName):
        dict = {}
        i = 0
        sql = "SELECT * FROM " + tableName
        for row in self.cursor.execute(sql):
            item = {"id":row[0],"title":row[1]}
            dict[str(i)] = item
            i += 1
        return str(dict)

    def close(self):
        self.cursor.close()
        self.connect.close()
main.py (使用之前封装好的类)

import socket
import sqlite #导入模块 自己命名的
import re

name = "diary"

sqlite.DB().initTable(name)
sqlite.DB().insertData(name, ("title100","content100"))
sqlite.DB().deletaData(name, 2)
sqlite.DB().updateData(name, 10, ("title300","content300"))
sqlite.DB().searchData(name, 1)
sqlite.DB().showAllData(name)
sqlite.DB().close()

接下类写一个比较完整的日志demo,可以用之前中级班应用Tkinter代码做修改
改后:



Screen Shot 2018-04-16 at 5.05.25 PM.png Screen Shot 2018-04-16 at 5.05.35 PM.png
代码:(这是我写的,但是仍旧运行不了!求大神赐教!)
diary.py
from tkinter import  * #导入 Tkinter 库
import os
import socket

def write():
    textVar.set("")                    #清空 entry
    text.delete("0.0","end")           #清空 text
    label.config(text = "写日记模式")    
    listBox.pack_forget()              #隐藏 listBox
    entry.pack()                       #显示 entry
    text.pack                          #显示 pack

def save():
    title = textVar.get() + ".txt"              # 获取标题
    content = text.get("0.0", "end")            # 获取内容
    
    if title != ".txt":
        # fileObj = open(title, "wb")             # 打开一个文件
        # fileObj.write(content.encode(encoding = "utf-8"))                  # 写入内容
        # fileObj.close()                         # 关闭打开的文件
        # label.config(text = "已保存") 

        s = socket.socket()
        s.connect(('127.0.0.1',1234))
        print(s.recv(1024))
        #将标题,内容写成字典
        dict = {'title':title,'content':str(content)}
        s.send(str(dict).encode(encoding = "utf-8"))
        data = s.recv(1024)
        s.close()
        label.config(text = data)
    else:
        label.config(text = "请输入标题") 

def read():
    listBox.delete(0,END)                       # 清空 listBox
    # dir = os.getcwd()                           # 获取当前目录
    # list =  os.listdir(dir)                     # 获取目录内所有文件

    showText = "看日记模式" 

    s = socket.socket()                  # 创建 socket 对象
    s.connect(('127.0.0.1',1234))       # 链接服务器
    print(s.recv(1024))                  # 打印信息
    s.send("read".encode(encoding = "utf-8"))       # 发送一个 read 字符串
    data = s.recv(2048)                  # 收到数据 (字符串格式)
    dict = eval(data)                  # 间数据转为字典格式
    s.close()                            # 关闭链接

    if len(list) == 0:                          # 如果当前没有日记
        showText += "(日记本是空的)"            # 设置提示  
    label.config(text = showText)

    for item in dict.values(): # 因为数据库中日记标题可能有相同的,加一个id 来区分一下
        string = str(item['id']) + ':' + item['title']
        listBox.insert(0,string)                  
      
    listBox.bind('<Double-Button-1>',showDiary) # 绑定双击事件

    entry.pack_forget()                         # 隐藏 entry
    text.pack_forget()                          # 隐藏 text
    listBox.pack()                              # 显示 listBox

def showDiary(event): 
    
    title = listBox.get(listBox.curselection()) # 获取点击的日记名
    showTitle = title[:-4]                      # 截取至倒数第4个字符(即不显示.txt)
    textVar.set(showTitle)                      # 设置日记标题

    id = title.split(':')[0] # 截取日记的id
    data = 'show' + id       # 拼接字符串

    s = socket.socket()        
    s.connect(('127.0.0.1',1234))
    print(s.recv(1024))
    s.send(data.encode(encoding = "utf-8"))
    data = s.recv(1024)               # 服务器返回数据
    content = eval(data)['content']   # 转为字典后取出 content 的值
    s.close()

    # fileObj = open(title, "r+")                 # 打开对应标题的文件
    # content = fileObj.read();                   # 获取文件内容
    text.delete("0.0", "end")                   # 清空 text
    text.insert("end", content)                 # 把内容显示在 text 上
    # fileObj.close()                             # 关闭打开的文件

    listBox.pack_forget()                       # 隐藏 listBox
    entry.pack()                                # 显示 entry
    text.pack()                                 # 显示 text

#创建日记文件夹
def initDiary():
    dir = os.getcwd()               # 获取当前.py目录
    list = os.listdir(dir)          # 获取当前目录中的所有文件
    haveDiary = False               # 设置一个变量,是否存在diary文件夹,默认为 False
    for item in list:               # 遍历
        if item == "diary":         # 判断是否存在 diary 文件夹
            haveDiary = True        # 如果有,设置 diary 为Ture
    if haveDiary == False:          # 如果 haveDiary 为 False
        os.mkdir("diary")           # 创建 diary 文件夹

    os.chdir("./diary")             # 改变 .py 工作目录到 diary 内
initDiary()

root = Tk() #创建窗口
root.geometry('500x400') #窗口的frame
root.title("窗口的名字")

saveBtn = Button(root, text = "Save",command=save)
saveBtn.pack(side=LEFT,anchor='sw') #pack 是一种布局方式 ancher是一种对齐方式

quitBtn = Button(root,text = "Exit")
quitBtn.pack(side=RIGHT,anchor="se")

#command=write 表示点击这个按钮时候,会执行 write 方法,然后我们来写一下 write 方法
writeBtn = Button(root, text="写日记", command=write)
writeBtn.pack(side=BOTTOM, anchor='s') 

readBtn = Button(root,text = "read",command=read)
readBtn.pack(side=BOTTOM)

label = Label(root)
label.pack()
label.config(text = "This is a demo")

textVar = StringVar()
entry = Entry(root, textvariable = textVar)
entry.pack()

listBox = Listbox(root, height = 300)

text = Text(root)
text.pack()


root.mainloop() #开始事件循环

这几节课我们做了很多插入、更改等操作,先清空一下我们的表
或者直接将 test.db 数据库删除也行,因为都是胡乱写入的测试数据

database.py
#!/usr/bin/env python
#coding:utf-8

import sqlite3                      

class DB:
    def __init__(self):
        self.connect = sqlite3.connect("test.db")
        self.cursor  = self.connect.cursor()

    def searchTable(self, tableName):
        flag = False
        self.cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
        for item in self.cursor.fetchall():
            if item[0] == tableName:
                flag = True
                break
        return flag

    def initTable(self, tableName):
        if self.searchTable(tableName) == False:
            sql = "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, content TEXT)"
            self.cursor.execute(sql)
            print(u"创建表成功")
        else:
            print(u"该表已存在")

    def insertData(self, tableName, data):
        sql = "INSERT INTO " + tableName + "(title, content) VALUES (?, ?)"
        self.cursor.execute(sql, data)
        self.connect.commit()
        return ("保存成功")

    def deleteData(self, tableName, id):
        sql = "DELETE FROM " + tableName + " WHERE id = " + str(id)
        self.cursor.execute(sql)
        self.connect.commit()
        return ("删除成功")

    def updateData(self, tableName, id, data):
        sql = "UPDATE " + tableName + " SET title = '" + data[0] + "', content = '" + data[1] + "' WHERE id = " + str(id)
        self.cursor.execute(sql)
        self.connect.commit()
        return ("修改成功")

    def searchData(self, tableName, id):
        sql = "SELECT * FROM " + tableName + " WHERE id = " + str(id)
        self.cursor.execute(sql)
        tup = self.cursor.fetchone()
        dict = {'title': tup[1], 'content': tup[2]}
        return str(dict)

    def showAllData(self, tableName):
        sql = "SELECT * FROM " + tableName 
        for row in self.cursor.execute(sql):
            print(row)

    def getDataDict(self, tableName):
        dict = {}
        i = 0
        sql = "SELECT * FROM " + tableName 
        for row in self.cursor.execute(sql):
            item = {'id':row[0],'title':row[1]} 
            dict[str(i)] = item
            i += 1
        return str(dict)

    def close(self):
        self.cursor.close()
        self.connect.close()

    def dropTable(self, tableName):
        sql = 'DROP TABLE IF EXISTS ' + tableName
        self.cursor.execute(sql)
        self.connect.commit()
        return ("表已删除或不存在")

    def clearTable(self, tableName):
        # 清空表数据
        sql  = "DELETE FROM " + tableName
        # 设置自增 id 为 0
        reset = "UPDATE sqlite_sequence SET seq = 0 WHERE name = '" + tableName + "'"
        # 注意 '" + tableName + "'" 这不是 3个' + 5个',而是两个双引号中间一个单引号
        # 为了加以区分这样来写,如果不拼接的话就是下面这样
        # "UPDATE sqlite_sequence SET seq = 0 WHERE name = 'diary'"
        self.cursor.execute(sql)
        self.cursor.execute(reset)
        self.connect.commit()
        return ("表已清空")

# 以下是改写为函数前的代码,不明白的可以看看理解一下

# # 创建一个名为 diary 的表,并设置一个 id 为自增主键,title、content 为 text 类型
# cursor.execute("CREATE TABLE diary (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, content TEXT)")

# # 向表中插入数据,因为是自增主键,id 可以写成 NULL,表中 id 值会是 1、2、3…… 递增
# cursor.execute("INSERT INTO diary VALUES (NULL, 'title1', 'content1')")
# # 或者也可以这样写
# cursor.execute("INSERT INTO diary(title, content) VALUES ('title2', 'content2')")
# # 查询表中所有数据,并输出
# for row in cursor.execute("SELECT * FROM diary"):
#     print row
# print u"***** 增 ***** \n"

# # 删除表中 id 为 1 的数据
# cursor.execute("DELETE FROM diary WHERE id = 1")
# # 再输出所以数据,验证是否删除成功
# for row in cursor.execute("SELECT * FROM diary"):
#     print row
# print u"***** 删 ***** \n"

# # 修改 id 为 2 的数据
# cursor.execute("UPDATE diary SET title = 'title0', content = 'content0' WHERE id = 2")
# # 再输出所以数据,验证是否修改成功
# for row in cursor.execute("SELECT * FROM diary"):
#     print row
# print u"***** 改 ***** \n"

# items = [("title0", "content0"),("title1", "content1"),("title2", "content2")]
# # executemany 一次向标准插入多条数据
# cursor.executemany("INSERT INTO diary(title, content) VALUES (?, ?)", items)
# print u"插入多条数据后的表:"
# for row in cursor.execute("SELECT * FROM diary"):
#     print row

# print u"查 id 为 5 的数据:"
# cursor.execute("SELECT * FROM diary WHERE id = 5")
# print cursor.fetchall()

# print u"查 title 为 title0 的数据:"
# cursor.execute("SELECT * FROM diary WHERE title = 'title0'")
# print cursor.fetchall()

# cursor.close()
# connect.close()
server.py
#!/usr/bin/env python
#coding:utf-8

import socket                      
import database
import re

s = socket.socket()                
s.bind(('127.0.0.1', 1234))      

s.listen(5)                       
while True:
    c, addr = s.accept()        
    print(u'连接地址为:', addr)
    c.send('成功链接至服务器...'.encode())
    # 客服端发来的数据
    # 1、'read'   
    #    表示点击看日记,则去读取数据库中所有日记的标题和 id
    # 2、'show5'  (5 为 id)  
    #    表示双击日记名,则去数据库中查找 id 为 5 的日记并返回
    # 3、'{"title": "cxy", "content": "adcd"}'
    #    这是一个由包含日记信息字典转成的字符串,则插入数据

    data = c.recv(1024)                                      # 接收客户端的数据(3种情况)
    if data:                            
        tableName = 'diary'                                  # 表名
        database.DB().initTable(tableName)                   # 创建表
        database.DB().showAllData(tableName)                 # 显示所有数据,方面我们看结果

        if data == 'read':                                   
            print('看日记')
            c.send(database.DB().getDataDict(tableName))     # 将返回数据发给客服端

        elif data[0:4] == 'show':                            # 判断字符串前4个字符是否为 show
            id = re.sub(r'\D', '', data)                     # 用正则删除非数字字符
            print('查日记:', id)
            c.send(database.DB().searchData(tableName, id).encode())  # 根据 id 查表中数据,发送结果

        else:
            dict = eval(data)                                # 将字符串转为字典
            print(dict)                                       # 打印,方便我们看结果
            tup = (dict['title'], dict['content'])           # 写成元组格式,方便数据插入
            print(tup)
            c.send(database.DB().insertData(tableName, tup).encode()) # 插入数据
        
        database.DB().close()                               
    c.close()

# 使用 database 模块 DB 类中方法的试例
# name = 'diary'
# database.DB().initTable(name)
# database.DB().insertData(name, ('title100','content100'))
# database.DB().deleteData(name, 2)
# database.DB().updateData(name, 10, ('title300','content300'))
# database.DB().searchData(name, 10)
# database.DB().showAllData(name)
# database.DB().close()

# 清空表、删除表的试例子
# database.DB().initTable('diary')
# print database.DB().insertData('diary', ('title100','content100'))
# print database.DB().insertData('diary', ('title100','content100'))
# print u'表中数据为:'
# database.DB().showAllData('diary') 
# print '\n'

# print database.DB().clearTable('diary')
# print u'表中数据为:'
# database.DB().showAllData('diary') 
# print '\n'

# print database.DB().insertData('diary', ('title100','content100'))
# print database.DB().insertData('diary', ('title100','content100'))
# print u'清空后再插入两条数据,id 又从 1 开始计数'
# database.DB().showAllData('diary')
# print '\n'

# print database.DB().dropTable('diary')
# database.DB().showAllData('diary') 

遇到问题(尚未解决)
Python3.0
点击read, 报错为:
Screen Shot 2018-04-16 at 5.11.08 PM.png Screen Shot 2018-04-16 at 5.11.01 PM.png

相关文章

网友评论

      本文标题:Python 高级 第四课(未完成。。)

      本文链接:https://www.haomeiwen.com/subject/ehmekftx.html