1. 程式人生 > >最全總結 | 聊聊 Python 資料處理全家桶(Mysql 篇)

最全總結 | 聊聊 Python 資料處理全家桶(Mysql 篇)

![image](https://upload-images.jianshu.io/upload_images/1466987-82ad628a151414ab?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 1\. 前言 在爬蟲、自動化、資料分析、軟體測試、Web 等日常操作中,除 JSON、YAML、XML 外,還有一些資料經常會用到,比如:Mysql、Sqlite、Redis、MongoDB、Memchache 等  一般情況下,我們都會使用特定的客戶端或命令列工具去操作;但是如果涉及到工程專案,將這部分資料操作整合到程式碼中使用才是王道 接下來,我將分幾篇文章,和大家一起聊聊 Python 操作這些資料的 最優 方案 本篇從使用最為廣泛的關係型資料庫 - Mysql 開始講起 ## 2\. 準備 首先,我們通過 Mysql 客戶端或命令列建立一個數據庫 xh 然後,在這個資料庫下建一張簡單的表 people 為了便於演示,這裡只建立了三個欄位:id、name、age,其中 id 為主鍵 ![image](https://upload-images.jianshu.io/upload_images/1466987-684986ad1f140bc2?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) Python 操作 Mysql 主要包含下面 3 種方式: * Python-MySql * PyMysql * SQLAlchemy 其中, Python-MySql 由 C 語法打造,介面精煉,效能最棒;但是由於環境依賴多,安裝複雜,已停止更新,僅支援 Python2 PyMysql 為替代 Python-Mysql 而生,純 Python 語言編寫的 Mysql 操作客戶端,安裝方便,支援 Python3 SQLAlchemy 是一個非常強大的 ORM 框架,不提供底層的資料庫操作,主要是通過定義模型對應資料表結構,在 Python Web 程式設計領域應用廣泛 由於 Python-MySql  不支援 Python3,所以本文只談後 2 種操作方式 ## 3\. PyMysql 首先,使用 pip 安裝依賴 ``` # 安裝依賴 pip3 install pymysql ``` 連線資料庫,獲取資料庫連線物件及遊標物件 使用 pymysql 中的 connect() 方法,傳入資料庫的 HOST 地址、埠號、使用者名稱、密碼、待操作資料庫的名稱,即可以獲取 資料庫的連線物件 然後,再通過資料庫連線物件,獲取執行資料庫具體操作的 遊標物件 ``` import pymysql # 資料庫連線 self.db = pymysql.connect(host='localhost', port=3306, user='root', password='**', database='xh') # 獲取遊標 self.cursor = self.db.cursor() ``` 接著,我們來實現增刪改查操作 1、新增 新增包含新增單條資料和多條資料 對於單條資料的插入,只需要編寫一條插入的 SQL 語句,然後作為引數執行上面遊標物件的 execute(sql) 方法,最後使用資料庫連線物件的 commit() 方法將資料提交到資料庫中 ``` # 插入一條資料 SQL_INSERT_A_ITEM = "INSERT INTO PEOPLE(name,age) VALUES('xag',23);" def insert_a_item(self): """ 插入一條資料 :return: """ try: self.cursor.execute(SQL_INSERT_A_ITEM) self.db.commit() except Exception as e: print('插入資料失敗') print(e) self.db.rollback() ``` 使用執行遊標物件的 executemany() 方法,傳入插入的 SQL 語句及 位置變數列表,可以實現一次插入多條資料 ``` # 插入多條資料SQL,name和age是變數,對應列表 SQL_INSERT_MANY_ITEMS = "INSERT INTO PEOPLE (name, age) VALUES(%s, %s)" # 待插入的資料 self.datas = [("張三", 23), ("李四", 24), ("王五", 25)] def insert_items(self): """ 插入多條記錄 :return: """ try: self.cursor.executemany(SQL_INSERT_MANY_ITEMS, self.datas) self.db.commit() except Exception as e: print("插入資料異常") self.db.rollback() ``` 需要注意的是,PyMysql 會將 SQL 語句中的所有欄位當做字串進行處理,所以這裡的 age 欄位在 SQL 中被當做字串處理 2、查詢 查詢分為三步,分別是: * 通過遊標物件執行具體的 SQL 語句 * 通過遊標物件,獲取到元組資料 * 遍歷元組資料,檢視結果 比如:檢視資料表中所有的記錄 ``` # 查詢所有記錄 SQL_QUERY_ALL = "SELECT * FROM PEOPLE;" def query(self): """查詢資料""" # 查詢所有資料 self.cursor.execute(SQL_QUERY_ALL) # 元組資料 rows = self.cursor.fetchall() # 列印結果 for row in rows: id = row[0] name = row[1] age = row[2] print('id:', id, ',name:', name, 'age:', age) ``` 如果需要按條件查詢某一條記錄,只需要修改 SQL 語句即可實現 ``` # 按id查詢 SQL_QUERY_WITH_CONDITION = "SELECT * FROM PEOPLE WHERE id={};" # 查詢id為5的記錄 self.cursor.execute(SQL_QUERY_WITH_CONDITION.format(5)) ``` 3、更新 和 新增操作 類似,更新操作也是通過遊標物件去執行更新的 SQL 語句,最後利用資料庫連線物件將資料真實更新到資料庫中 ``` # 更新(通過id去更新) SQL_UPDATE = "UPDATE PEOPLE SET name='%s',age=%s WHERE id=%s" def update(self): """ 更新資料 :return: """ sql_update = SQL_UPDATE % ("王五五", 30, 5) print(sql_update) try: self.cursor.execute(sql_update) self.db.commit() except Exception as e: self.db.rollback() print('更新資料異常') print(e) ``` 4、刪除 刪除操作同查詢、新增操作類似,只需要變更 SQL 語句即可 ``` # 刪除(通過id去刪除資料) SQL_DELETE = "DELETE FROM PEOPLE WHERE id=%d" ​ def delete(self): """ 刪除記錄 :return: """ try: # 刪除的完整sql sql_del = SQL_DELETE % (5) self.cursor.execute(sql_del) self.db.commit() except Exception as e: # 發生錯誤時回滾 self.db.rollback() print(e) ``` 最後,我們需要將遊標物件和資料庫連線物件資源釋放掉 ``` def teardown(self): # 釋放資源 self.cursor.close() self.db.close() ``` ## 4. SQLAlchemy 首先,使用 SQLAlchemy 操作 Mysql 資料庫同樣先需要安裝依賴庫 ``` # 安裝依賴包 pip3 install sqlalchemy ``` 通過 SQLAlchemy 的內建方法 declarative_base() 建立一個基礎類 Base 然後,自定義一個 Base 類的子類,內部定義靜態變數,和上面資料表 people 中的欄位一一對應 ``` from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy.ext.declarative import declarative_base # 基礎類 Base = declarative_base() # 自定義的表 class People(Base): # 表名 __tablename__ = 'people' # 定義欄位 id = Column(Integer, primary_key=True) name = Column(String(255)) age = Column(Integer) def __repr__(self): """ 便於列印結果 :return: """