Python中使用MySQL的BLOB字串類型

一直想在MySQL中直接存儲二進制數據,嘗試到今天也沒有解決這個問題,但仍有幾點要記錄一下,比較亂:

  1. 可惜設置不了0編號,就將就着在這裏寫下版本吧。Python 2.4.4,MySQLdb 1.2.1_p2,MySQL 5.0.32
  2. 不要使用'%r',比如'INSERT INTO mytbl VALUES (%r)',這樣做就很沒意思了,讀取一個二進文件內容到data,然後再使用file.write('%r' % data)寫入到文件,打開看以下你就會明白。使用'%r'還不如使用base64編碼。
  3. MySQLdb.escape_string對二進制數據使用沒有問題,escape後的數據只增大了一點。據說新的版本下這個可以省略。
  4. 使用'INSERT INTO mytbl VALUES (%s)' % MySQLdb.escape_string(data)應該是對的,但會提示UnicodeDecodeError。
  5. 第4點中的錯誤,懷疑是數據庫的charset關係,我的db的character_set_name()返回"latin1";也有可能是組織SQL命令字串時就出現的問題。
  6. Python Codebook, Page 355, Chapter 8.7 Storing a BLOB in a MYSQL Database,有時間仔細看看。
  7. 使用MySQL的LOAD_FILE函數是跳過以上問題的好方法,看開始時我總是得到NULL,折騰了半天發現要使用這個函數需要得到file權限,這個權限必須設置給全局(又折騰了一會),(using ON *.* syntax)。詳細可以參見MySQL的GRANT語法
    GRANT FILE ON *.* to you@localhost identified by "secret";
  8. 使用LOAD_FILE得到的結果正是我所需要的,如果第4步成功,也應該是這樣。
  9. 更正:第5點中的錯誤是從cursors.py的146行產生的:query = query.encode(charset)。帶二進制的MySQL命令字串是可以產生的,但對它使用execute就會有這樣的問題。MySQL中倒是有binary的charset類型,但python中沒有,所以不能在創建數據庫時指定charset爲binary。MySQL字符集相關資料可以參見這裏
  10. 萬般無奈之下我決定抄下Python Codebook, Chapter 8.7.2的代碼來運行,竟然沒遇到折磨我的encode錯誤,再把程序中的二進制數據換成我測試用的圖片數據,還是正常。仔細看下,原來我用execute的方式不一樣:
    cursor.execute(query % binary_data)
    而codebook裏是這樣寫的:
    cursor.execute(query, binary_data)
    看看"/usr/lib/python2.4/site-packages/MySQLdb/cursors.py"中的execute,就知道區別在那裏了,codebook的代碼當然沒有encode錯誤,因爲不會對二進制數據操作。

終於結束摸索了,總結一下:

  • 插入BLOB不需要使用特別的CHARACTER SET,和這個問題無關
  • 如果要插入二進制數據,使用"execure(query, binary_data)"的方式
  • 在新的版本下不要對binary_data使用escape_string函數
  • 從數據庫中獲取到的BLOB的數據類型是array,我通常使用array.tofile來直接保存到文件,當然也可以使用其它的方式,請自己查找python::array的資料
  • 如果使用LOAD_FILE,請確保你的MySQL用戶有FILE的權限,另外文件要可訪問並且不要太大。

Welcome to PicVew.com

 
發佈了46 篇原創文章 · 獲贊 0 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章