用Python批量从本地导数据到postgres数据库,比人工导入快十倍,爽
目錄
1.序言
2.邏輯思路
3.代碼技術要點
4.完整代碼實現
1.序言
在數據采集時,可能會從別的部門得到的一堆的Excel文檔,這些文檔零零散散,不好做數據分析,需要把這些數據存入數據庫中,方便管理和分析。
文檔數量較少時,手工把Excel數據表存入數據庫,工作量還不是很大,但是當有成百上千個文檔時,一個一個錄入,這就需要費很多時間了。
這時候,使用Python進行數據批量導入就省時省力得多,而且這個程序保存下來后,可以長期利用,一勞永逸。
2.邏輯思路
實現的邏輯圖
3.代碼技術要點
定義一個漢字轉拼音的函數,獲取漢字的首字母小寫
def get_fist_name(long_str):return pinyin.get_initial(long_str, delimiter="").lower()根據postgressql語法構造SQL語句,包括建表語句和字段注釋語句。
如果只處理一張表還好,因為表的字段數量是固定的,但是當批量處理不同字段數量的表時,這個難度有很大提升,方法是計算總字段數N,N-1個(%s,)相乘,后面再加一個(%s)。
print("insert into %s values(%s%s)"%(a,"%s,"*(len(N)-1),'%s'))out: insert into table_name values(%s,%s,%s,%s,%s)為了滿足SQL語句要求,要去掉括號。讀取第一行,用split去掉中文或英文括號后面的內容,只保留括號前的內容(單位(元)–>單位),再構造SQL語句。
file_str="" for i in range(len(data.loc[0])):column_English=get_fist_name(data.loc[0][i].split('(')[0].split('(')[0])column_English_name.append(column_English +' '+ 'VARCHAR') #去除中文括號file_title_English='gn'+'_'+get_fist_name(root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0])column_name=get_fist_name(data.values.tolist()[0][i].split('(')[0].split('(')[0])file_str=file_str+"comment on column %s.%s is '%s';"%(file_title_English,column_name,data.values.tolist()[0][i])構造一個標準化的標題:廣西_單位名稱_文件名稱
file_title='廣西'+'_'+root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0]使用try----except來執行SQL語句
try: #建表cursor.execute("CREATE TABLE {}(%s)".format(file_title_English)%",".join(column_English_name))#添加表注釋cursor.execute("comment on table {} is '{}';".format(file_title_English,file_title) )#添加字段注釋cursor.execute( file_str )#讀取表的內容轉換成list格式,便于批量存入數據庫data_list=data.values.tolist()[1:]#插入數據 sql = "insert into %s values(%s%s)"%(file_title_English,"%s,"*(len(data.loc[0])-1),'%s')cursor.executemany(sql, data_list) #提交SQL作業conn.commit() except Exception as e:print (e)print(name)pass對于需要導入的Excel文件不能缺失第一行標題,標準的格式如下:
4.完整代碼
1.單文件導入模式
在以下代碼中修改file_name和root就可以實現一個個文件導入數據庫,這樣做的好處是在批量導入報錯的情況下,方便修改錯誤的地方。
import psycopg2 import pandas as pd import pinyin import shutil import os#獲取漢字首字母 def get_fist_name(long_str):return pinyin.get_initial(long_str, delimiter="").lower()#創建游標,鏈接數據庫 conn=psycopg2.connect(database='gndsj',user='postgres',password='postgres',host='172.17.5.99',port='5432') cursor=conn.cursor()file_name='信息匯總表' root=r'F:\大數據\數據清洗入庫\正在入庫數據1\單位名稱'path=os.path.join(root,file_name+'.xlsx') data=pd.read_excel(path) #讀取文件內容 data.fillna('') #去掉空格單元格#讀取表的字段名稱 column_English_name=[] #獲取中文名稱,轉換成英文,用于建表#判斷兩列的拼音是否相同,相同則要改成+1,因為建表時不能有相同字段 for i in range(len(data.loc[0])):for j in range(1,len(data.loc[0])):if i!=j and get_fist_name(data.values.tolist()[0][i].split('(')[0].split('(')[0])==get_fist_name(data.values.tolist()[0][j].split('(')[0].split('(')[0]): data.loc[0][j].split('(')[0].split('(')[0]=data.loc[0][j].split('(')[0].split('(')[0]+'1'data.loc[0][i].split('(')[0].split('(')[0]=data.loc[0][i].split('(')[0].split('(')[0]breakfile_str="" for i in range(len(data.loc[0])):column_English=get_fist_name(data.loc[0][i].split('(')[0].split('(')[0])column_English_name.append(column_English +' '+ 'VARCHAR') #去除中文括號file_title_English='gn'+'_'+get_fist_name(root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0])column_name=get_fist_name(data.values.tolist()[0][i].split('(')[0].split('(')[0])file_str=file_str+"comment on column %s.%s is '%s';"%(file_title_English,column_name,data.values.tolist()[0][i]) file_title='廣西'+'_'+root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0] #保留原樣中文 # department=root.split('\\')[-1]try: #建表cursor.execute("CREATE TABLE {}(%s)".format(file_title_English)%",".join(column_English_name))#添加表注釋cursor.execute("comment on table {} is '{}';".format(file_title_English,file_title) )#添加字段注釋cursor.execute( file_str )#讀取表的內容轉換成list格式,便于批量存入數據庫data_list=data.values.tolist()[1:]#插入數據 sql = "insert into %s values(%s%s)"%(file_title_English,"%s,"*(len(data.loc[0])-1),'%s')cursor.executemany(sql, data_list) #提交SQL作業conn.commit() except Exception as e:print (e)print(name)passcursor.close() conn.close()2.批量導入模式
在數據格式統一,滿足SQL語法的前提下,使用以下這個程度可以實現數據自動化導入,剩下的時間就是到處逛逛,上個廁所、喝杯茶、撩撩妹。
import psycopg2 import pandas as pd import pinyin import shutil import os#獲取漢字首字母 def get_fist_name(long_str):return pinyin.get_initial(long_str, delimiter="").lower()#建立已入庫文件 def make_file(path_out,department):if os.path.exists(path_out+'\\'+department):passelse:os.mkdir(path_out+'\\'+department)path_from=r'F:\大數據\數據清洗入庫\正在入庫數據1\單位名稱'#存入數據庫的表名稱存放地址 data_insert=[] #創建游標,鏈接數據庫 conn=psycopg2.connect(database='gndsj',user='postgres',password='postgres',host='172.17.5.99',port='5432') cursor=conn.cursor()for root,dirs,files in os.walk(path_from):for name in files:path=os.path.join(root,name) #獲取文件絕對路徑file_name=name.split('.')[0] #獲取文件表名稱data=pd.read_excel(path) #讀取文件內容#讀取表的字段名稱column_English_name=[] #獲取中文名稱,轉換成英文,用于建表 # column_Chinese_name=[] #獲取中文名稱,用于注釋字段#判斷兩列的拼音是否相同,相同則要改成+1,因為建表時不能有相同字段for i in range(len(data.loc[0])):for j in range(1,len(data.loc[0])):if get_fist_name(data.values.tolist()[0][i].split('(')[0].split('(')[0])==get_fist_name(data.values.tolist()[0][j].split('(')[0].split('(')[0]): data.loc[0][j]=data.loc[0][j]+'1'breakfile_str=""for i in range(len(data.loc[0])):column_English=get_fist_name(data.loc[0][i].split('(')[0].split('(')[0])column_English_name.append(column_English +' '+ 'VARCHAR') #去除中文括號 # column_Chinese_name.append(data.loc[1][i]) #保留原樣中文file_title_English='gn'+'_'+get_fist_name(root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0])column_name=get_fist_name(data.values.tolist()[0][i].split('(')[0].split('(')[0])file_str=file_str+"comment on column %s.%s is '%s';"%(file_title_English,column_name,data.values.tolist()[0][i]) #讀取表的名稱,用于建表注釋 file_title='廣西'+'_'+root.split('\\')[-1]+'_'+file_name.split('(')[0].split('(')[0] #保留原樣中文department=root.split('\\')[-1]try: #建表cursor.execute("CREATE TABLE {}(%s)".format(file_title_English)%",".join(column_English_name))#添加表注釋cursor.execute("comment on table {} is '{}';".format(file_title_English,file_title) )#添加字段注釋cursor.execute( file_str )#讀取表的內容轉換成list格式,便于批量存入數據庫data_list=data.values.tolist()[1:]#插入數據 sql = "insert into %s values(%s%s)"%(file_title_English,"%s,"*(len(data.loc[1])-1),'%s')cursor.executemany(sql, data_list) #獲取存入數據庫的表data_insert.append(file_name) #提交SQL作業conn.commit() except Exception as e:print (e)print(name)passcursor.close() conn.close()修復一個bug
在建表時,varchar沒有設定字符長度時,默認長度為0,為了讓它全部設定為255,需在建表時加以說明
ALTER TABLE table_name alter COLUMN column_name type varchar(255); column_English_name.append(column_English +' '+ 'VARCHAR') 變成 column_English_name.append(column_English +' '+ 'VARCHAR(255)')在建表時沒有這句的話,可以批量修改。
運行下列程序—>導出結果到Excel—>從Excel復制程序到數據庫管理工具Navicat運行
select c.relname 表名,a.attname 字段 , 'alter table "public"."' ||c.relname|| '"'|| ' alter COLUMN ' || a.attname || ' type varchar(255)'||';' from pg_class c,pg_attribute a,pg_type t,pg_description d where a.attnum>0 and a.attrelid=c.oid and a.atttypid=t.oid and d.objoid=a.attrelid and d.objsubid=a.attnum and c.relname in (select tablename from pg_tables where schemaname='public' and position('_2' in tablename)=0) order by c.relname,a.attnum運行這段程序時,如果遇到文本內容超長時,仍然會報錯,可以先屏蔽這一行,往后繼續運行,運行完了手工修改,或修改為格式 text 在運行。
總結
以上是生活随笔為你收集整理的用Python批量从本地导数据到postgres数据库,比人工导入快十倍,爽的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python调包师_为“Python调包
- 下一篇: python value iterati