python數據持久化

Python的數據持久化操作主要是六類:普通文件、DBM文件、Pickled對象存儲、shelve對象存儲、對象數據庫存儲、關係數據庫存儲。

 

      普通文件不解釋了,DBM就是把字符串的鍵值對存儲在文件裏:

 

Python代碼
  1. % python  
  2. >>> import anydbm                             
  3. >>> file = anydbm.open('movie''c')        # make a DBM file called 'movie'  
  4. >>> file['Batman'] = 'Pow!'                 # store a string under key 'Batman'  
  5. >>> file.keys( )                                 # get the file's key directory  
  6. ['Batman']  
  7. >>> file['Batman']                          # fetch value for key 'Batman'  
  8. 'Pow!'  

 Pickled就是把對象序列化到文件,可以存儲複雜類型:

 

Python代碼
  1. % python  
  2. >>> table = {'a': [123],  
  3.              'b': ['spam''eggs'],  
  4.              'c': {'name':'bob'}}  
  5. >>>  
  6. >>> import pickle  
  7. >>> mydb  = open('dbase''w')  
  8. >>> pickle.dump(table, mydb)  

 下面是反序列化:

 

Python代碼
  1. % python  
  2. >>> import pickle  
  3. >>> mydb  = open('dbase''r')  
  4. >>> table = pickle.load(mydb)  
  5. >>> table  
  6. {'b': ['spam''eggs'], 'a': [123], 'c': {'name''bob'}}  

 shelve存儲差不多就是DBM和Pickled方式的結合,以鍵值對的形式把對象序列化到文件:

 

Python代碼
  1. % python  
  2. >>> import shelve  
  3. >>> dbase = shelve.open("mydbase")  
  4. >>> object1 = ['The''bright', ('side''of'), ['life']]  
  5. >>> object2 = {'name''Brian''age'33'motto': object1}  
  6. >>> dbase['brian']  = object2  
  7. >>> dbase['knight'] = {'name''Knight''motto''Ni!'}  
  8. >>> dbase.close( )  

 取數據:

 

Python代碼
  1. % python  
  2. >>> import shelve  
  3. >>> dbase = shelve.open("mydbase")  
  4. >>> len(dbase)                             # entries  
  5. 2  
  6.   
  7. >>> dbase.keys( )                          # index  
  8. ['knight''brian']  
  9.   
  10. >>> dbase['knight']                        # fetch  
  11. {'motto''Ni!''name''Knight'}  

     對象數據庫的存儲沒怎麼了解,因爲不習慣用它存儲數據。感覺應該和shelve差不多吧,只是把數據保存到了數據庫裏(其實還是一個文件嘛),然後增加了些事務之類的高級功能。


     Python中關係數據庫的存儲是重點,操作關係數據庫最“簡單”的就是直接用DB-API,就像Java裏的JDBC;當然,數據結構複雜了、設計要求高了,就得找些ORM框架偷懶了,主要有獨立的SQLAlchemy,Django的自帶ORM等。這部分內容還是下一篇博客寫吧,我不喜歡文章拉得長長的……


Python中操作關係數據庫最直接的就是用DB-API了,流程一般是:連接、執行SQL語句、提交、斷開。以MySQL爲例,下面是各步驟的代碼示例:

 

首先是連接:

 

Python代碼
  1. % python  
  2. >>> import MySQLdb  
  3. >>> conn = MySQLdb.connect(host='localhost', user='root', passwd='python')  

 

接着便可以執行語句了,但在執行SQL語句前要先獲取指針:

 

Python代碼
  1. >>> curs = conn.cursor( )  
  2. >>> curs.execute('create database peopledb')  
  3. 1L  
  4. >>> curs.execute('use peopledb')  
  5. 0L  
  6. >>> tblcmd = 'create table people (name char(30), job char(10), pay int(4))'  
  7. >>> curs.execute(tblcmd)  
  8. 0L  

 

添加數據:

 

Python代碼
  1. >>> curs.execute('insert people values (%s, %s, %s)', ('Bob''dev'5000))  
  2. 1L  
  3. >>> curs.executemany('insert people values (%s, %s, %s)',  
  4. ...          [ ('Sue''mus''70000'),  
  5. ...            ('Ann''mus''60000')])  
  6. 2L  
  7. >>> conn.commit( )  

 

執行查詢:

 

Python代碼
  1. >>> curs.execute('select * from people')  
  2. 6L  
  3. >>> curs.fetchall( )  
  4. (('Bob''dev'5000L), ('Sue''mus'70000L), ('Ann''mus'60000L), ('Tom',  
  5. 'mgr'100000L))  

 

 

執行完數據庫操作記得斷開連接:

 

Python代碼
  1. conn.close( )        # close, _ _del_ _ call rollback if changes not committed yet  

 

 

      如果數據結構不是很複雜,配合Python強大的列表解析能力,不用ORM框架也是很方便的;或者自己封裝對象映射也不是很難。


     如果使用了Django框架,可以使用它自帶的ORM工具來操作數據庫。首先當然是編寫實體類(或者叫模型)了:

 

Java代碼
  1. from django.db import models  
  2.   
  3. class Musician(models.Model):  
  4.     first_name = models.CharField(max_length=50)  
  5.     last_name = models.CharField(max_length=50)  
  6.     instrument = models.CharField(max_length=100)  
  7.   
  8. class Album(models.Model):  
  9.     artist = models.ForeignKey(Musician)  
  10.     name = models.CharField(max_length=100)  
  11.     release_date = models.DateField()  
  12.     num_stars = models.IntegerField()  

 

 Python的代碼已經很清楚了,類對應表,成員變量對應表的列,列屬性由models.XXXField(...)定義。如果實體類沒有顯式定義主鍵,Django會默認加上一句:

 

Python代碼
  1. id = models.AutoField(primary_key=True)  

 

 Django裏可以這樣定義枚舉型數據:

 

Python代碼
  1. class Person(models.Model):  
  2.     GENDER_CHOICES = (  
  3.         (u'M', u'Male'),  
  4.         (u'F', u'Female'),  
  5.     )  
  6.     name = models.CharField(max_length=60)  
  7.     gender = models.CharField(max_length=2, choices=GENDER_CHOICES)  

 

 對於關聯關係,在做列的映射定義時可以這麼寫:

 

Python代碼
  1. poll = models.ForeignKey(Poll)  
  2. sites = models.ManyToManyField(Site)  
  3. place = models.OneToOneField(Place")  

 

 在Django裏定義關聯關係還有更多功能,詳細的還是看官方文檔吧~

      Django的Model基類中已經定義了基本的數據庫操作,因爲所有的實體類都是繼承自Model類,所以也就有了這些操作。例如新建並保存一個person只需要這麼做:

 

Python代碼
  1. >>> p = Person(name="Fred Flinstone", gender="M")  
  2. >>> p.save()  

 

 Django會通過查詢對象的主鍵是否存在來決定該UPDATE還是INSERT,當然你也可以強制框架執行某種操作。如果你不滿意框架自帶的方法,可以重寫它:

 

Python代碼
  1. class Blog(models.Model):  
  2.     name = models.CharField(max_length=100)  
  3.     tagline = models.TextField()  
  4.   
  5.     def save(self, *args, **kwargs):  
  6.         do_something()  
  7.         super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.  
  8.         do_something_else()  

 發現沒,Django裏存取數據不需要那種session,最討厭Hibernate裏的session了,總是報“Session Closed”錯誤……


      Python還有一個獨立的ORM框架——SQLAlchemy。功能更強大,支持的數據庫也比Django自帶的ORM工具要多。它有兩種建立實體類的方法。

      一種是分開定義,再將表定義和類定義映射起來。首先是建立表的定義:

Python代碼
  1. >>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey  
  2. >>> metadata = MetaData()  
  3. >>> users_table = Table('users', metadata,  
  4. ...     Column('id', Integer, Sequence('user_id_seq'), primary_key=True),  
  5. ...     Column('name', String(50)),  
  6. ...     Column('fullname', String(50)),  
  7. ...     Column('password', String(12))  
  8. ... )  

 接着定義實體類:

Python代碼
  1. >>> class User(object):  
  2. ...     def __init__(self, name, fullname, password):  
  3. ...         self.name = name  
  4. ...         self.fullname = fullname  
  5. ...         self.password = password  

 這還沒完,還要把他們映射起來:

Python代碼
  1. >>> from sqlalchemy.orm import mapper  
  2. >>> mapper(User, users_table)   

 這樣的過程有點像Hibernate裏將XML的Map文件和實體類的映射。Hibernate中還可以方便的直接用註釋在實體類中完成與表的映射,當然SQLAlchemy也有直接的方法:

Python代碼
  1. >>> from sqlalchemy.ext.declarative import declarative_base  
  2.   
  3. >>> Base = declarative_base()  
  4. >>> class User(Base):  
  5. ...     __tablename__ = 'users'  
  6. ...  
  7. ...     id = Column(Integer, primary_key=True)  
  8. ...     name = Column(String)  
  9. ...     fullname = Column(String)  
  10. ...     password = Column(String)  

 作爲一個獨立的ORM框架,實體類的存取當然就不會像Django那樣集成的那麼完美了,SQLAlchemy裏存取數據也是要Session的:

Python代碼
  1. >>> from sqlalchemy.orm import sessionmaker  
  2. >>> Session = sessionmaker(bind=engine)  

 這裏的engine對象需要這樣建立:

Python代碼
  1. >>> from sqlalchemy import create_engine  
  2. >>> engine = create_engine('<span style="font-family: monospace; white-space: normal; color: #333333; line-height: 20px;">dialect+driver://user:password@host/dbname[?key=value..]</span>', echo=True)  

 對於存取操作,如果是保存就這麼寫:

Python代碼
  1. >>> ed_user = User('ed''Ed Jones''edspassword')  
  2. >>> session.add(ed_user)  

 如果要查詢,就是類似的這種形式:

Python代碼
  1. >>> our_user = session.query(User).filter_by(name='ed').first()   

 執行完一些數據操作,必要的時候要提交或是回滾:

Python代碼
  1. >>> session.rollback()  
  2. 或者  
  3. >>> session.commit()  

        SQLAlchemy框架還有一個衍生產品——Elixir,在SQLAlchemy的基礎上對其映射方式做了些封裝,使得實體類的定義有點類似Django中的定義方式。

      以上便是這兩天對Python中數據存儲的一些學習記錄。話說Django的ORM與它的其他模塊結合的很緊密,不好單獨使用;SQLAlchemy雖然強大,但風格不太喜歡,所以下一步打算深入兩個ORM框架的代碼,看看他們是怎麼實現的。一方面好抉擇用哪一個,另外也可以看看在自己的應用中能否自己做一個簡單的ORM。


轉載:http://gaogaochao1.blog.163.com/blog/static/79810971201101955038248/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章