作为一个sqlalchemy的新手,完全是基于自身需求来学习它的。最近遇到一个问题:目前手头上有一大堆日志文件,按天组织在一起,每一天的日志文件单独放在同一个目录下。每个目录下的文件的个数不尽相同,有多有少,每个文件里面包含若干条记录,因此,每天的这些日志文件所包含的总记录条数也是不一样的,少则20多万条,多则6000多万条。为了处理方便,现在需要将这些记录全部放进数据库中。一共有47天,如果将这47天的所有日志记录全部放进数据库的同一张表中,那么在查询的时候将会很慢。于是,首先需要对日志记录进行分割,将不同的日志放进不同的表中,自然的想法就是将同一天的所有日志放进同一张表中,这样实现起来最简单。按照这个想法,需要在数据库中创建47个表,然后将每个目录下的日志文件中的所有记录插进对应的表中。
用过sqlalchemy的都知道,它是python的一款著名的ORM框架,它实现了把关系数据库的表结构映射到对象上。按照sqlalchemy的一般用法,我们需要为数据库中的每个表定义一个与之对应的类。如果我们有多张表的话,就要定义多个类,但是在这里,很明显的一点是,我们需要创建的这些表的字段完全一样,只是表名不一样,因此我们需要一种方法只定义一个用来描述表结构的类,然后通过某种方式让这个类与所有表产生关联。通过在网上查找资料,找到了一种实现这个需求的方法,即在定义表所对应的类时,使用__abstract__ = True语句,这样就可以使用python的type方法动态生成数据库表所对应的类了。下面看代码。
# 使用__abstract__=True语句定义所有数据库表对应的父类
class ConLogClass(Base):
__abstract__ = True
# __tablename__ == should be 'conlog_%s'
id = Column(Integer, primary_key=True)
device_id = Column(Integer)
sample_time = Column(Integer)
sip = Column(String(16))
dip = Column(String(16))
# 存储表ID与类的对应关系
cid_class_dict = {}
# 根据表ID得到类
def get_conlog_model(cid):
if cid not in cid_class_dict:
cls_name, table_name = get_class_name_and_table_name(cid)
cls = type(cls_name, (ConLogClass, ), {'__tablename__': table_name})
cid_class_dict[cid] = cls
return cid_class_dict[cid]
# 根据表ID得到类名和表名
def get_class_name_and_table_name(self, cid):
return 'ConLog%s' % cid, 'conlog_%s' % cid
# 创建数据库引擎
engine = create_engine('mysql+mysqldb://root:123456@127.0.0.1:3306/logs')
# 创建session
DBSession = sessionmaker(bind=engine)
session = DBSession()
cid = 1112
# 根据表ID得到数据库表所对应的类
model = get_conlog_model(cid)
# 通过上面得到的类创建一条记录
re = model(device_id=data[‘device_id’],
sample_time = data[’sample_time’],
sip = data[’sip’],
dip = data[‘dip’])
# 将记录加入session
session.add(re)
# 提交添加
session.commit()
至此,使用sqlalchemy动态生成数据库表的功能就实现了,接下里只需要实现日志的插入和查询功能即可。原理还是一样,根据不同的表ID得到不同的类模型,通过类模型生成记录。