上次的那幾個(gè)腳本這次全部整合到了一起,而且后面發(fā)現(xiàn)了一個(gè)可以使用的ODBC包,于是這次采用的方式就很簡(jiǎn)單了,直接通過ODBC將InterBase數(shù)據(jù)庫(kù)中的數(shù)據(jù)全部取出來之后通過Python的sqlalchemyORM框架直接連接遠(yuǎn)程的MySQL數(shù)據(jù)庫(kù),之后便可以方便的傳遞數(shù)據(jù)了,當(dāng)然,作為我的終極完善版本,自動(dòng)模式和手動(dòng)模式是少不了的了,在自動(dòng)模式中將自動(dòng)檢查InterBase數(shù)據(jù)庫(kù)是否存在,如果不存在則自動(dòng)restore,然后自己創(chuàng)建InterBase的數(shù)據(jù)源,之后便可以取出數(shù)據(jù)了,下面是流程圖。
那么下面就是講解代碼的時(shí)候咯~
這次的這個(gè)腳步主要分為三個(gè)函數(shù),main函數(shù),odbc函數(shù)和restore函數(shù),由于手動(dòng)模式包含在自動(dòng)模式中,那么我就只介紹自動(dòng)模式了。
我在腳本中定義了一個(gè)字典用來存儲(chǔ)腳本的配置信息,用戶可以在字典中定義自己需要的功能和數(shù)據(jù)庫(kù)信息等。
#定義一個(gè)配置字典,將所需的參數(shù)添加在字典中方便改動(dòng)setting = {#設(shè)置啟動(dòng)模式'Operate_type':OPERATE_AUTO_RESTORE,#備份文件的地址'gbk_path':'C://XXX//DB.gbk',#需要恢復(fù)的InterBase數(shù)據(jù)庫(kù)地址'gdb_path':'C:///XXX///DB.GDB',#設(shè)置需要連接的MySQL數(shù)據(jù)庫(kù)的用戶名,密碼,ip地址和端口號(hào)'username':'root', 'passWord':'root', 'port':'3306', 'dbname':'test', 'localhost':'127.0.0.1',#設(shè)置需要連接的ODBC的名字以及用戶名和密碼'DSN':'XXX','UID':'SYSDBA','PWD':'masterkey'}
在腳本啟動(dòng)的時(shí)候就通過判斷來確定用戶是以何種模式進(jìn)行的腳本,緊接著運(yùn)行適合的腳本
if __name__ == '__main__': #判斷啟動(dòng)模式是自動(dòng)模式還是手動(dòng)模式 if setting['operate_type']==OPERATE_AUTO_RESTORE: #檢查數(shù)據(jù)庫(kù)是否存在,如果存在將跳過restore if os.path.isfile('C://XXX//DB.GDB') == False: restore() odbc() main() else: PRint 'The database has been exist, will skip restore...' odbc() main() elif setting['operate_type']==OPERATE_AUTO_EXPORT: main()
當(dāng)Python判斷InterBase數(shù)據(jù)庫(kù)不存在之后便執(zhí)行restore來恢復(fù)數(shù)據(jù)庫(kù)
#自動(dòng)模式中恢復(fù)數(shù)據(jù)庫(kù)的方法def restore(): os.system('gbak -c -user "sysdba" -password "masterkey" "'+setting['gbk_path']+'" "127.0.0.1:'+setting['gdb_path']+'"')
之后便是自動(dòng)創(chuàng)建InterBase的ODBC數(shù)據(jù)源了,當(dāng)然首先要安裝InterBase的驅(qū)動(dòng)了,網(wǎng)上有很多,我就不一一的列出了,由于是在windows平臺(tái)上運(yùn)行的,所以很方便的就可以使用添加注冊(cè)表的形式將需要的數(shù)據(jù)源添加進(jìn)系統(tǒng)中了,當(dāng)然,既然是通過注冊(cè)表導(dǎo)入的那么就必然會(huì)產(chǎn)生出一個(gè)注冊(cè)表文件了,我將它默認(rèn)的生成在C盤的根目錄,然后在導(dǎo)入完成之后再刪除掉,這樣就在腳本運(yùn)行完之后也不會(huì)產(chǎn)生垃圾了。
#下面這個(gè)字符串創(chuàng)建了所需要的ODBC數(shù)據(jù)源,并將數(shù)據(jù)源中的數(shù)據(jù)庫(kù)地址改為restore輸出的數(shù)據(jù)庫(kù)地址def odbc(): odbcreg = '''Windows Registry Editor Version 5.00[HKEY_CURRENT_USER/Software/ODBC/ODBC.INI][HKEY_CURRENT_USER/Software/ODBC/ODBC.INI/kmk]"Driver"="C:///WINDOWS///system32///OdbcFb32.dll""Description"="""Dbname"="'''+setting['gdb_path']+'''""Client"="""User"="SYSDBA""Role"="""CharacterSet"="NONE""JdbcDriver"="IscDbc""ReadOnly"="N""NoWait"="N""LockTimeoutWaitTransactions"="""Dialect"="3""QuotedIdentifier"="Y""SensitiveIdentifier"="N""AutoQuotedIdentifier"="N""UseSchemaIdentifier"="0""SafeThread"="Y""Password"="DKEBFJENHFCOBHGHLAIMNAAFICELEAEGDNMFNOGALAMHBBGCHFADNKCBPPGMANOGIEKENIOPHDIPBIECPLLLCBIKEJKMJLPLIB"[HKEY_CURRENT_USER/Software/ODBC/ODBC.INI/ODBC Data Sources]"kmk"="Firebird/InterBase(r) driver" ''' #在C盤根目錄下新建一個(gè)臨時(shí)的注冊(cè)表文件用來將新建的數(shù)據(jù)源導(dǎo)入 fp = open('C://db007.reg','w') try: fp.write(odbcreg) except Exception,e: print e finally: fp.close() #執(zhí)行生成的數(shù)據(jù)源注冊(cè)表文件 os.system('regedit /s C://db007.reg') #將臨時(shí)產(chǎn)生的注冊(cè)表文件刪除 os.remove('C://db007.reg')
緊接著就是我們最關(guān)鍵的main函數(shù)咯~
當(dāng)然了,這次和上次一樣使用的是Python中SQLAlchemyORM的框架了,所以第一件事便是連接數(shù)據(jù)庫(kù),獲得session了,不過再次之前還是要先構(gòu)建類與表的映射關(guān)系了。
#創(chuàng)建一個(gè)基類Base = declarative_base()#定義一個(gè)User類與數(shù)據(jù)庫(kù)進(jìn)行映射class User(Base): __tablename__ = 'User' NAME= Column(Integer, primary_key=True) PASSWORD= Column(Integer) .......
然后在獲得Session之后便可以連接ODBC了,通過SQL語句將InterBase數(shù)據(jù)庫(kù)中的數(shù)據(jù)取出來。
#創(chuàng)建數(shù)據(jù)庫(kù)的連接 mysql_db = create_engine( 'mysql://'+setting['username']+':'+setting['password']+'@'+setting['localhost']+/ ':'+setting['port']+'/'+setting['dbname'],echo=False) Base.metadata.bind=mysql_db Base.metadata.create_all(mysql_db) #創(chuàng)建一個(gè)Session Session = sessionmaker(bind=mysql_db) session = Session() #pdb.set_trace() #創(chuàng)建與ODBC數(shù)據(jù)源的連接 conn = pyodbc.connect('DSN='+setting['DSN']+';UID='+setting['UID']+';PWD='+setting['PWD']+'') curs = conn.cursor() #通過SQL語句得到一個(gè)對(duì)象 dbf = curs.execute('select *from User')
下面就是自動(dòng)模式與手動(dòng)模式都必須進(jìn)過的步驟了~通過循環(huán)將數(shù)據(jù)提交到MySQL中,當(dāng)然,為了防止數(shù)據(jù)庫(kù)中已經(jīng)有了數(shù)據(jù),那么就在添加之前檢查數(shù)據(jù)庫(kù)中是否有這個(gè)數(shù)據(jù),如果有的話便跳過這次添加,繼續(xù)后面的步驟。然后在每1000次添加之后提交一次數(shù)據(jù),以減輕數(shù)據(jù)的壓力,最后在循環(huán)外將除以1000的余數(shù)統(tǒng)一再存入數(shù)據(jù)庫(kù)中。
#循環(huán)的將對(duì)象中的數(shù)據(jù)保存到User類中 commint = 0 for line1 in dbf: #檢查數(shù)據(jù)庫(kù)中的數(shù)據(jù)是否有數(shù)據(jù),如果沒有則加入數(shù)據(jù) exist = session.query(User).filter(User.ID == line1.ID,User.NAME == line1.NAME).count() if exist>0: continue u = User() u.NAME = line1.NAME ...... u.PASSWORD = line1.PASSWORD session.add(u) commint = commint+1 #當(dāng)循環(huán)了1000次之后進(jìn)行一次提交 if commint%1000==0: try: session.commit() #pdb.set_trace() session.flush() except: print 'error' session.rollback() #將剩余的數(shù)據(jù)進(jìn)行提交 try: session.commit() session.flush() except Exception , e: print e session.rollback() session.close()
至此,這個(gè)是用ODBC讀取數(shù)據(jù)然后在保存在MySQL的Python腳本就寫完了,斷斷續(xù)續(xù)進(jìn)過了一周多的日子,我實(shí)習(xí)的第一個(gè)正式任務(wù)也算是完美收官了,曾經(jīng)在校園里學(xué)了幾年的J2EE,萬萬沒想到最后卻來做了Python和數(shù)據(jù)庫(kù)。。。。不知道后面的日子里還有什么樣奇怪的任務(wù)等著我~~當(dāng)然!我依舊不會(huì)放棄web的!加班狗努力!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注