用Python寫一個向資料庫填充資料的小工具
一. 背景
公司又要做一個新專案,是一個合作型專案,我們公司出web展示服務,合作伙伴線下提供展示資料。
而且本次專案是資料統計展示為主要功能,並沒有研發對應的資料接入介面,所有展示資料來源均來自資料庫查詢,
所以驗證資料沒有別的入口,只能通過在資料庫寫入資料來進行驗證。
二. 工具
Python+mysql
三.前期準備
前置:當然是要先準備好測試方案和測試用例,在準備好這些後才能目標明確將要開發自動化小工具都要有哪些功能,避免走彎路
3.1 跟開發溝通
1)確認資料庫連線方式,庫名 ;
2)測試所涉及到的表名;
3)每個表是對哪部分業務造成影響;
4)表之間的關聯關係,同業務模組之間的不同表之間是否有關聯欄位;
5)表中個欄位資料是否有特殊來源,如使用者ID、廠商名稱一類與業務有一定關聯程度的欄位,一定要確認好是可以隨機生成的 還是 需要從指定表中獲取欄位
3.2 設計小工具最終要實現的效果
我設計這個小工具就希望它可以完成兩件事情
1) 生成sql語句,並且能寫入進入mysql資料庫
2) 資料我寫入sql的統計結果,方便使用它直接與頁面結果進行比對
3.3 給自己加個油! 我一定可以的!
四.開始程式設計
***因為程式碼內實際業務邏輯比較強,所以下面只寫出一些示例啦~
4.1 先處理一下基礎資料
1)因為我將要寫入的內容涉及到全國的省市名稱和省市行政區域程式碼,所以先找開發要了一個他們使用的全國省市名稱及程式碼對照json,然後處理成字典格式備用
2)編寫寫入sql的語句頭
通過配置檔案的方式將各個表的寫入語句的前半句語法格式和寫入欄位名稱編輯好。
之後每次使用的時候只需通過配置檔案讀取對應表的寫入語句再拼裝上要寫入的內容就是一個完整的sql語句了
使用配置檔案的模式主要是可以統一管理,並且可以保持後面生成環節的程式碼整潔
[veh_scrap] veh = INSERT INTO zqy_veh_scrap_sto (zqy_id, vin, pack_num, scrap_time, bat_is_scrap,wmi,epname,epcode,province_code,city_code,submit_time) values
4.2 編寫工具模組
1)編寫隨機工具
因為寫入的內容大部分欄位需要不重複,所以使用random模組,定義不同的方法生成各種型別隨機資料,如隨機身份證號 隨機姓名 隨機編碼 隨機ID 等等...
再生成寫入資料的時候,就可以引用這個隨機工具模組引用裡面的方法取隨機值,以保證寫入資料的唯一性
例:
def random_vin(): """ 生成隨機vin :return: """ return ''.join( random.sample(['Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], 17))
2)pyMysql模組引入並封裝可用工具
因為最終要將內容寫入,所以要使用pyMysql模組,將組裝好的sql語句執行寫入
需要封裝的內容有 資料庫連結 獲取遊標 語句執行方法 資料庫查詢方法 刪除語句方法
例:
def get_conn(): conn = pymysql.connect( host=, port=, user=, password=, database=, charset='utf8') return conn def execut_sql(sql): try: conn = get_conn() cur = conn.cursor() cur.execute(sql) conn.commit() print("資料庫執行成功") cur.close() except Exception as e: print(str(e)) print(sql) # 有異常就回滾 conn.rollback() # 關閉連線 cur.close() conn.close() def select_one_sql(sql): try: conn = get_conn() cur = conn.cursor() cur.execute(sql) results = cur.fetchone() #print(results) cur.close() return results except Exception as e: print(str(e)) # 關閉連線 cur.close() conn.close()
3)讀取配置的模組
因為我們將sql語句的頭通過配置檔案進行管理,那麼就需要一個讀取配置的模組或方法,因為我比較菜 所以為了看起來更加清晰 就用模組來進行管理了
import configparser cfg_path = 'rebulid_generate_sql_git\base_data\sql_header.ini' cfg = configparser.ConfigParser() cfg.read(cfg_path,encoding='utf-8') def get_config_data(section,options): return cfg.get(section,options)
4) 編寫生成寫入資訊的方法
因為我們在處理基礎資料的時候就已經寫好了sql寫入語句頭了,所以現在只要生成它後面的values值就可以了,這步就是生成他values值的步驟
建立一個列表,根據寫入語句內欄位的順序生成對應欄位的值並新增至建立的列表中。對應欄位的內容如果是隨機值,就使用之前準備好的隨機模組,使用裡面的方法生成隨機值;如果是需要從其他表中獲取的值,則通過封裝好的qymysql的查詢方法進行搜尋並引用。
例:
def recycle_veh_scrap(prov, city): """ 報廢車輛入庫表 :return: """ prov_info = random_util.random_city_code(prov, city) # 獲取當地所有公司資訊 company = search_factory_info.get_company_data(prov, city) # 獲取vin vin = random_util.random_vin() # 生成資料容器 insert_data = [] # 生成隨機zqy_id,寫入列表 insert_data.append(random_util.random_id()) # 生成隨機vin,寫入列表 insert_data.append(vin) # 生成隨機電池包數,寫入列表 insert_data.append(random.randint(1, 10)) # 生成報廢時間,寫入列表 insert_data.append(random_util.random_date()) # bat_is_scrap insert_data.append('1') # wmi insert_data.append(vin[0:3].upper()) # 生成報廢企業名稱,寫入列表 insert_data.append(company[0]) # 生成報廢企業程式碼,寫入列表 insert_data.append(company[1]) # 獲取省級程式碼,寫入列表 insert_data.append(prov_info[0]) # 獲取市級程式碼,寫入列表 insert_data.append(prov_info[1]) # 資料提交時間為當前資料生成時間,寫入列表 insert_data.append(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))return insert_data
5) 編寫統計方法
因為我們寫入的值是隨機的,所以沒有標準去判斷最終系統寫入的內容是否正確。
那就需要我們將需要對比的值取出儲存並統計,用於最後對照使用。
取值的過程會在語句寫入之前一步完成,現在要先準備一個數據處理的模組,以便對取出的至進行統計。
可以先準備幾個比較常用的,例如列表內同類值 列表內數值求和 字典合併等方法,如果後面再有更復雜的格式,再單獨編寫。
例:
def TongJiQi(list): # 列表內容統計器,對列表內的重複項進行數量統計 count_dict = dict() for item in list: if item in count_dict: count_dict[item] += 1 else: count_dict[item] = 1 return count_dict def qiuhe(data_list): """ 對列表內的數值進行求和 :param data_list: :return: """ total = 0 for ele in range(0, len(data_list)): total = total + data_list[ele] return total
以上,準備工作就都做好了,下面就要開始真正的寫入了
4.3 生成資料並拼裝為sql語句
1) 通過生產sql語句數量來控制迴圈,將sql頭與值拼裝在一起,並將拼裝好的結果進行寫入
2) 在迴圈生成寫入值的過程中,將需要統計或計算的值取出單獨儲存,在寫入結束後再進行技術統計輸出統計結果
def write_sql(prov, city, des_prov, des_city) # 通過配置檔案獲取sql頭 sql = config_util.get_config_data('veh_scrap', 'pack_out') # 控制迴圈 i = 0 # 建立列表,用於收集需要統計計算的資料 company_num = [] des_company_num = [] while i < sql_num: i += 1 # 取生成的values值 data = _crap_out(prov, city, des_prov, des_city) # 收集需要統計的資料 company_num.append(data[8]) des_company_num.append(data[4]) # 拼裝sql語句 sql = sql + str(tuple(data)) + ',' # 最後一組資料後的,刪除掉 right_sql = sql.strip(',') # 拼裝上結尾的; fullsql作為返回值 full_sql = right_sql + ';' # print(full_sql) # 執行寫入 pymysql_util.execut_sql(full_sql)
print('上報企業統計: ' + str(
statistics_util.TongJiQi(company_num)))
print('去向企業統計: ' + str(
statistics_util.TongJiQi(des_company_num)))
這樣一個表的資料就寫入成功了,只需要調整寫入條數就可以想寫入多少條就寫入多少條,還可以直接輸出你關心的欄位統計結果。
多個數據庫表的話可以就是將以上的生產資料和寫入資料的步驟複製,按照表名和欄位稍作修改就可以了。
再將所有表的資料生成和寫入都編寫完成後,可以編寫一個小工具的入口,給自己編寫一個選擇器
每次只要輸入對應的數字就可以執行對應的方法,寫入資料並輸出統計結果啦
def main(prov, city, sql_num, sour_prov, sour_city): """ 啟動資料自動寫入的主方法 :return: """ features_type = input("請選擇生成資料所屬功能模組 1.車輛報廢 2.梯次利用 3.資源再生") if features_type == '1': scrapped_main.write_sql(prov, city, sql_num, des_prov=sour_prov, des_city=sour_city) elif features_type == '2': echelon_use_main.write_main(prov, city, sql_num, sour_prov, sour_city) elif features_type == '3': recycle_main.write_main(sql_num, prov, city, sour_prov, sour_city)
五.總結
以上只是一個工作過程中倉促搞出的一個小東西,還有很多不足。拋轉引玉,拿出來跟大家分享一下我的思路,希望能對大家有所幫助!
還有我趟過的坑,也記錄一下吧
1.不要只管悶頭寫,寫完一個表的時候就執行試一下,不只要看資料庫寫進去了 主要是看看要測試的平臺能不能看到,之前因為開發忘了跟我說一個欄位條件,我全都寫完了也執行成功了,但就是上不去平臺,最後不得不大改一遍
2.隨時跟開發溝通確認任何一個不確定的問題,因為有的表可能會用不到,表內的某些欄位沒有用,表設計不明確的時候等等,這些時候都要跟他們確認好再繼續動手寫,防止無用功。
3.這只是輔助測試的工具,要控制住開發工具的時間,防止測試工作的延誤。
&n