设为首页 收藏本站
查看: 858|回复: 0

[经验分享] 简单比较Python的数据持久化操作

[复制链接]

尚未签到

发表于 2018-8-13 07:04:29 | 显示全部楼层 |阅读模式
  Python中操作关系数据库最直接的就是用DB-API了,流程一般是:连接、执行SQL语句、提交、断开。以MySQL为例,下面是各步骤的代码示例:
  首先是连接:

Python代码

  • % python
  • >>> import MySQLdb
  • >>> conn = MySQLdb.connect(host='localhost', user='root', passwd='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
  

  
>>> 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( )
  

  
>>> 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))
  

  
>>> 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
  

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

  如果数据结构不是很复杂,配合Python强大的列表解析能力,不用ORM框架也是很方便的;或者自己封装对象映射也不是很难。
  

  如果使用了Django框架,可以使用它自带的ORM工具来操作数据库。首先当然是编写实体类(或者叫模型)了:

Java代码

  • 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()
  

  
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)
  

  
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)
  

  
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")
  

  
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()
  

  
>>> 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()
  

  
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))
  • ... )
  

  
>>> 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
  


  
>>>>  
...     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)
  

  
>>> 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)
  

  
>>> from sqlalchemy.ext.declarative import declarative_base
  

  
>>> Base = declarative_base()

  
>>>>  
...     __tablename__ = 'users'
  
...

  
...    >  
...     name = Column(String)
  
...     fullname = Column(String)
  
...     password = Column(String)
  

  作为一个独立的ORM框架,实体类的存取当然就不会像Django那样集成的那么完美了,SQLAlchemy里存取数据也是要Session的:

Python代码

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

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

  这里的engine对象需要这样建立:

Python代码

  • >>> from sqlalchemy import create_engine
  • >>> engine = create_engine('<span style=&quot;font-family: monospace; white-space: normal; color: rgb(51, 51, 51); line-height: 20px;&quot;>dialect+driver://user:password@host/dbname[?key=value..]</span>', echo=True)
  

  
>>> from sqlalchemy import create_engine
  
>>> engine = create_engine('dialect+driver://user:password@host/dbname[?key=value..]', echo=True)
  

  对于存取操作,如果是保存就这么写:

Python代码

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

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

  如果要查询,就是类似的这种形式:

Python代码

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

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

  

  执行完一些数据操作,必要的时候要提交或是回滚:

Python代码

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

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

  SQLAlchemy框架还有一个衍生产品——Elixir,在SQLAlchemy的基础上对其映射方式做了些封装,使得实体类的定义有点类似Django中的定义方式。
  以上便是这两天对Python中数据存储的一些学习记录。话说Django的ORM与它的其他模块结合的很紧密,不好单独使用;SQLAlchemy虽 然强大,但风格不太喜欢,所以下一步打算深入两个ORM框架的代码,看看他们是怎么实现的。一方面好抉择用哪一个,另外也可以看看在自己的应用中能否自己 做一个简单的ORM。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-550855-1-1.html 上篇帖子: Python urllib模块的URL编码解码功能 下篇帖子: python参数(加星号的参数含义)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表