美文网首页
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