上次的那幾個腳本這次全部整合到了一起,而且后面發現了一個可以使用的ODBC包,於是這次采用的方式就很簡單了,直接通過ODBC將InterBase數據庫中的數據全部取出來之后通過Python的sqlalchemyORM框架直接連接遠程的MySQL數據庫,之后便可以方便的傳遞數據了,當然,作為我的終極完善版本,自動模式和手動模式是少不了的了,在自動模式中將自動檢查InterBase數據庫是否存在,如果不存在則自動restore,然后自己創建InterBase的數據源,之后便可以取出數據了,下面是流程圖。
那么下面就是講解代碼的時候咯~
這次的這個腳步主要分為三個函數,main函數,odbc函數和restore函數,由於手動模式包含在自動模式中,那么我就只介紹自動模式了。
我在腳本中定義了一個字典用來存儲腳本的配置信息,用戶可以在字典中定義自己需要的功能和數據庫信息等。
#定義一個配置字典,將所需的參數添加在字典中方便改動 setting = { #設置啟動模式 'operate_type':OPERATE_AUTO_RESTORE, #備份文件的地址 'gbk_path':'C:\\XXX\\DB.gbk', #需要恢復的InterBase數據庫地址 'gdb_path':'C:\\\XXX\\\DB.GDB', #設置需要連接的MySQL數據庫的用戶名,密碼,ip地址和端口號 'username':'root', 'password':'root', 'port':'3306', 'dbname':'test', 'localhost':'127.0.0.1', #設置需要連接的ODBC的名字以及用戶名和密碼 'DSN':'XXX','UID':'SYSDBA','PWD':'masterkey'}
在腳本啟動的時候就通過判斷來確定用戶是以何種模式進行的腳本,緊接着運行適合的腳本
if __name__ == '__main__': #判斷啟動模式是自動模式還是手動模式 if setting['operate_type']==OPERATE_AUTO_RESTORE: #檢查數據庫是否存在,如果存在將跳過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()
當Python判斷InterBase數據庫不存在之后便執行restore來恢復數據庫
#自動模式中恢復數據庫的方法 def restore(): os.system('gbak -c -user "sysdba" -password "masterkey" "'+setting['gbk_path']+'" "127.0.0.1:'+setting['gdb_path']+'"')
之后便是自動創建InterBase的ODBC數據源了,當然首先要安裝InterBase的驅動了,網上有很多,我就不一一的列出了,由於是在windows平台上運行的,所以很方便的就可以使用添加注冊表的形式將需要的數據源添加進系統中了,當然,既然是通過注冊表導入的那么就必然會產生出一個注冊表文件了,我將它默認的生成在C盤的根目錄,然后在導入完成之后再刪除掉,這樣就在腳本運行完之后也不會產生垃圾了。
#下面這個字符串創建了所需要的ODBC數據源,並將數據源中的數據庫地址改為restore輸出的數據庫地址 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盤根目錄下新建一個臨時的注冊表文件用來將新建的數據源導入 fp = open('C:\\db007.reg','w') try: fp.write(odbcreg) except Exception,e: print e finally: fp.close() #執行生成的數據源注冊表文件 os.system('regedit /s C:\\db007.reg') #將臨時產生的注冊表文件刪除 os.remove('C:\\db007.reg')
緊接着就是我們最關鍵的main函數咯~
當然了,這次和上次一樣使用的是Python中SQLAlchemyORM的框架了,所以第一件事便是連接數據庫,獲得Session了,不過再次之前還是要先構建類與表的映射關系了。
#創建一個基類 Base = declarative_base() #定義一個User類與數據庫進行映射 class User(Base): __tablename__ = 'User' NAME= Column(Integer, primary_key=True) PASSWORD= Column(Integer) .......
然后在獲得Session之后便可以連接ODBC了,通過SQL語句將InterBase數據庫中的數據取出來。
#創建數據庫的連接 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) #創建一個Session Session = sessionmaker(bind=mysql_db) session = Session() #pdb.set_trace() #創建與ODBC數據源的連接 conn = pyodbc.connect('DSN='+setting['DSN']+';UID='+setting['UID']+';PWD='+setting['PWD']+'') curs = conn.cursor() #通過SQL語句得到一個對象 dbf = curs.execute('select *from User')
下面就是自動模式與手動模式都必須進過的步驟了~通過循環將數據提交到MySQL中,當然,為了防止數據庫中已經有了數據,那么就在添加之前檢查數據庫中是否有這個數據,如果有的話便跳過這次添加,繼續后面的步驟。然后在每1000次添加之后提交一次數據,以減輕數據的壓力,最后在循環外將除以1000的余數統一再存入數據庫中。
#循環的將對象中的數據保存到User類中 commint = 0 for line1 in dbf: #檢查數據庫中的數據是否有數據,如果沒有則加入數據 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 #當循環了1000次之后進行一次提交 if commint%1000==0: try: session.commit() #pdb.set_trace() session.flush() except: print 'error' session.rollback() #將剩余的數據進行提交 try: session.commit() session.flush() except Exception , e: print e session.rollback() session.close()
至此,這個是用ODBC讀取數據然后在保存在MySQL的Python腳本就寫完了,斷斷續續進過了一周多的日子,我實習的第一個正式任務也算是完美收官了,曾經在校園里學了幾年的J2EE,萬萬沒想到最后卻來做了Python和數據庫。。。。不知道后面的日子里還有什么樣奇怪的任務等着我~~當然!我依舊不會放棄web的!加班狗努力!