簡單比較Python的數據持久化操做

轉自http://smartzxy.iteye.com/blog/680431python

簡單比較Python的數據持久化操做(一)

最近喜歡上了Python,喜歡它的簡潔高效,喜歡它的「無所不能」。sql

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

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

Python代碼session

% python  
>>> import anydbm                             
>>> file = anydbm.open('movie', 'c')        # make a DBM file called 'movie'  
>>> file['Batman'] = 'Pow!'                 # store a string under key 'Batman'  
>>> file.keys( )                                 # get the file's key directory  
['Batman']  
>>> file['Batman']                          # fetch value for key 'Batman'  
'Pow!'

Pickled就是把對象序列化到文件,能夠存儲複雜類型:數據結構

Python代碼app

% python  
>>> table = {'a': [1, 2, 3],  
             'b': ['spam', 'eggs'],  
             'c': {'name':'bob'}}  
>>>  
>>> import pickle  
>>> mydb  = open('dbase', 'w')  
>>> pickle.dump(table, mydb)

下面是反序列化:框架

Python代碼ide

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

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

Python代碼

% python  
>>> import shelve  
>>> dbase = shelve.open("mydbase")  
>>> object1 = ['The', 'bright', ('side', 'of'), ['life']]  
>>> object2 = {'name': 'Brian', 'age': 33, 'motto': object1}  
>>> dbase['brian']  = object2  
>>> dbase['knight'] = {'name': 'Knight', 'motto': 'Ni!'}  
>>> dbase.close( )

取數據:

Python代碼

% python  
>>> import shelve  
>>> dbase = shelve.open("mydbase")  
>>> len(dbase)                             # entries  
2  
  
>>> dbase.keys( )                          # index  
['knight', 'brian']  
  
>>> dbase['knight']                        # fetch  
{'motto': 'Ni!', 'name': 'Knight'}

對象數據庫的存儲沒怎麼了解,由於不習慣用它存儲數據。感受應該和shelve差很少吧,只是把數據保存到了數據庫裏(其實仍是一個文件嘛),而後增長了些事務之類的高級功能。

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

簡單比較Python的數據持久化操做(二)

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

首先是鏈接:

Python代碼

% python  
>>> import MySQLdb  
>>> conn = MySQLdb.connect(host='localhost', user='root', passwd='python')

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

Python代碼

>>> curs = conn.cursor( )  
>>> curs.execute('create database peopledb')  
1L  
>>> curs.execute('use peopledb')  
0L  
>>> tblcmd = 'create table people (name char(30), job char(10), pay int(4))'  
>>> curs.execute(tblcmd)  
0L

添加數據:

Python代碼

>>> curs.execute('insert people values (%s, %s, %s)', ('Bob', 'dev', 5000))  
1L  
>>> curs.executemany('insert people values (%s, %s, %s)',  
...          [ ('Sue', 'mus', '70000'),  
...            ('Ann', 'mus', '60000')])  
2L  
>>> conn.commit( )

執行查詢:

Python代碼

>>> curs.execute('select * from people')  
6L  
>>> curs.fetchall( )  
(('Bob', 'dev', 5000L), ('Sue', 'mus', 70000L), ('Ann', 'mus', 60000L), ('Tom',  
'mgr', 100000L))

執行完數據庫操做記得斷開鏈接:

Python代碼

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

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

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

Python代碼

from django.db import models  
  
class Musician(models.Model):  
    first_name = models.CharField(max_length=50)  
    last_name = models.CharField(max_length=50)  
    instrument = models.CharField(max_length=100)  
  
class Album(models.Model):  
    artist = models.ForeignKey(Musician)  
    name = models.CharField(max_length=100)  
    release_date = models.DateField()  
    num_stars = models.IntegerField()

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

Python代碼

id = models.AutoField(primary_key=True)

Django裏能夠這樣定義枚舉型數據:

Python代碼

class Person(models.Model):  
    GENDER_CHOICES = (  
        (u'M', u'Male'),  
        (u'F', u'Female'),  
    )  
    name = models.CharField(max_length=60)  
    gender = models.CharField(max_length=2, choices=GENDER_CHOICES)

對於關聯關係,在作列的映射定義時能夠這麼寫:

Python代碼

poll = models.ForeignKey(Poll)  
sites = models.ManyToManyField(Site)  
place = models.OneToOneField(Place")

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

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

Python代碼

>>> p = Person(name="Fred Flinstone", gender="M")  
>>> p.save()

Django會經過查詢對象的主鍵是否存在來決定該UPDATE仍是INSERT,固然你也能夠強制框架執行某種操做。若是你不滿意框架自帶的方法,能夠重寫它:

Python代碼

class Blog(models.Model):  
    name = models.CharField(max_length=100)  
    tagline = models.TextField()  
  
    def save(self, *args, **kwargs):  
        do_something()  
        super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.  
        do_something_else()

發現沒,Django裏存取數據不須要那種session,最討厭Hibernate裏的session了,老是報「Session Closed」錯誤……

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

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

Python代碼

>>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey  
>>> metadata = MetaData()  
>>> users_table = Table('users', metadata,  
...     Column('id', Integer, Sequence('user_id_seq'), primary_key=True),  
...     Column('name', String(50)),  
...     Column('fullname', String(50)),  
...     Column('password', String(12))  
... )

接着定義實體類:

Python代碼

>>> class User(object):  
...     def __init__(self, name, fullname, password):  
...         self.name = name  
...         self.fullname = fullname  
...         self.password = password

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

Python代碼

>>> from sqlalchemy.orm import mapper  
>>> mapper(User, users_table)

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

Python代碼

>>> from sqlalchemy.ext.declarative import declarative_base  
  
>>> Base = declarative_base()  
>>> class User(Base):  
...     __tablename__ = 'users'  
...  
...     id = Column(Integer, primary_key=True)  
...     name = Column(String)  
...     fullname = Column(String)  
...     password = Column(String)

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

Python代碼

>>> from sqlalchemy.orm import sessionmaker  
>>> Session = sessionmaker(bind=engine)

這裏的engine對象須要這樣創建:

Python代碼

>>> from sqlalchemy import create_engine  
>>> 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代碼

>>> ed_user = User('ed', 'Ed Jones', 'edspassword')  
>>> session.add(ed_user)

若是要查詢,就是相似的這種形式:

Python代碼

>>> our_user = session.query(User).filter_by(name='ed').first()

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

Python代碼

>>> session.rollback()  
或者  
>>> session.commit()

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

話說Django的ORM與它的其餘模塊結合的很緊密,很差單獨使用;SQLAlchemy雖然強大,但風格不太喜歡,因此下一步打算深刻兩個ORM框架的代碼,看看他們是怎麼實現的。一方面好抉擇用哪個,另外也能夠看看在本身的應用中可否本身作一個簡單的ORM。

相關文章
相關標籤/搜索