#本脚本兼容了python2.x和3.x版本,使用SQLAlchemy ORM连接sqlserver或者MySQL,实现一个用户洗牌的应用
from os.path importdirnameimportpymysqlfrom pymysql.err importInternalErrorfrom random importrandrangefrom distutils.log importwarn as printffrom sqlalchemy importColumn,Integer,String,create_engine,exc,ormfrom sqlalchemy.ext.declarative importdeclarative_base#导入本地应用模块(ushuffle_dbU)必要的常量和工具函数,这是为了避免到处复制、黏贴相同的代码
from ushuffle_dbU importDBNAME,NAMELEN,randName,FIELDS,tformat,cformat,setup#dialect+driver://username:password@host:port/database
DSNs ={'mysql':'mysql+pymysql://root:Jwxjs123456@localhost/%s' %DBNAME,'sqllite':'sqllite:///:memory:','sql server':'mssql+pymssql://sa:Jwxjs123456@localhost/%s' %DBNAME,
}#SQLALchemy的声明层。
base =declarative_base()class Users(base):#继承Base类
__tablename__ = 'users' #映射的数据库表名
login =Column(String(NAMELEN))
userid= Column(Integer,primary_key =True)
projid=Column(Integer)def __str__(self): #返回易于阅读的数据行的字符串格式
return ''.join(map(tformat,(self.login,self.userid,self.projid)))classSQLALchemyTest(object):#初始化函数尽可能的得到一个可用的数据库,保存其连接
def __init__(self,dsn):try:
eng= create_engine(dsn)#,echo = True)#尝试使用dsn创建数据库引擎,echo设置为True可使得我们能看到ORM生成的SQL语句
printf('*****创建数据库引擎成功')exceptImportError:raise RuntimeError()#创建失败。一般来说,引擎创建失败意味着SQLAlchemy不支持所选的数据库,会抛出ImportError
try:
eng.connect()#如果数据库引擎创建成功,则尝试创建数据库连接
printf('*****连接数据库%s成功' %DBNAME)except (exc.InternalError,InternalError):#如果创建连接失败,一般意味着数据库本身不可达。此例中是因为目标数据库不存在
eng = create_engine( dirname(dsn),echo = True)#dirname返回dsn的目录。其实就是os.path.split(path)的第一个元素。效果相当于dsn去掉数据库
eng.execute('create database %s' %DBNAME).close()
printf('新建数据库%s成功' %DBNAME)
eng.create_engine(dsn,echo=True)
printf('连接数据库%s成功' %DBNAME)#创建数据库引擎连接之后,需要创建一个会话对象Session,其实是一个factory。
#sessionmaker()也可以在create_engine之前创建,然后等到数据库引擎连接创建之后,调用Session.configure(bind=)实现绑定
Session = orm.sessionmaker(bind=eng)#Session()可以创建一个绑定到数据库的对象。但是到此为止,它还没有打开任何的连接。
#当它第一次被调用的时候,会尝试从数据库引擎连接池中检索一个链接,该连接会一直被持有直到所有的任务都被提交或者Session对象被关闭
self.ses =Session()#将用户的表和数据库引擎作为 实例的属性保存下来。意味着这张表的所有操作都会被绑定到这个指定的引擎中。
self.users = Users.__table__self.eng= self.users.metadata.bind = eng#引擎和表的元数据进行了额外的绑定,意味着这张表的所有操作都会绑定到这个指定的引擎中
definsert(self):
self.ses.add_all(Users(login= who,userid=userid,projid=randrange(1,5)) for who,userid inrandName())
self.ses.commit()defupdate(self):
fr= randrange(1,5)
to= randrange(1,5)
i= -1users= self.ses.query(Users).filter_by(projid =fr).all()for i ,user inenumerate(users):
user.projid=to
self.ses.commit()
printf('\n %s 个用户名从 %s 更改到 %s' % (i+1,fr,to))defdelete(self):
rm= randrange(1,5)
i= -1users= self.ses.query(Users).filter_by(projid =rm).all()for i,user inenumerate(users):
self.ses.delete(user)
self.ses.commit()
printf('组号为%s的共%s个用户被删除' % (rm,i+1))deffinish(self):
self.ses.connection().close()defdbDump(self):
printf('\n%s' % ''.join(map(cformat,FIELDS)))
users=self.ses.query(Users).all()for user inusers:
printf(user)
self.ses.commit()def __getattr__(self,attr):#drop和create方法实际上只需要调用表的drop()和create()方法即可,不用我们自己单独编写。这里使用委托机制——当属性查找失败的时候会调用__getattr__()方法。
return getattr(self.users,attr)#使用help(getattr)来获取帮助。getattr()获取对象的属性,getattr(x,'y')相当于执行x.y。
defmain():
printf('连接%s数据库' %DBNAME)
db=setup()if db not inDSNs:
printf('\n ERROR:%s 数据库不被支持,程序退出')return
try:
orm=SQLALchemyTest(DSNs[db])exceptRuntimeError:
printf('\nERROR: %s 数据库不支持,程序退出')
printf('\n***创建users表()')
orm.drop(checkfirst= True)#orm.create()
printf('\n***创建users表,成功!!!')
printf('%%%插入数据')
orm.insert()
orm.dbDump()
printf('\n随机将用户进行分组')
orm.update()
orm.dbDump()
printf('\n !!!随机删除用户')
orm.delete()
orm.dbDump()
printf('\n***删除表格')
orm.drop()
printf('\n关闭数据库连接!')
orm.finish()if __name__ == '__main__':
main()