以Python的持久方式存储模拟结果?

时间:2010-03-25 01:32:07

标签: python sqlalchemy persistence

背景:我正在对一组数据进行多次模拟。对于每个课程,我都会为学生分配项目。每个课程之间的区别在于我将学生的顺序随机化,以便所有学生都能获得他们想要的项目。我在电子表格(即Excel)中写出了一些分配,它基本上看起来像这样(微小的快照,实际的表扩展到几千个会话,大约100个学生)。

|          | Session 1 | Session 2 | Session 3 |
|----------|-----------|-----------|-----------|
|Stu1      |Proj_AA    |Proj_AB    |Proj_AB    |
|----------|-----------|-----------|-----------|
|Stu2      |Proj_AB    |Proj_AA    |Proj_AC    |
|----------|-----------|-----------|-----------|
|Stu3      |Proj_AC    |Proj_AC    |Proj_AA    |
|----------|-----------|-----------|-----------|

现在,处理分配的代码目前在对象中存储 a 会话。下次运行分配时,对象将被覆盖。

因此,我真正想做的是存储所有分配结果。这一点非常重要,因为我后来需要从数据中获取信息,例如:哪个项目Stu1被分配到最多或可能有多受欢迎Proj_AC(分配了多少次/会话数) )。

Question(s):
我可以使用哪些方法来持续存储这样的会话信息?基本上,每个会话输出都需要在结束之后和开始下一个分配周期之前将其自身添加到存储库。

朋友建议的一个解决方案是使用SQLAlchemy将这些结果映射到关系数据库。我有点喜欢这个想法,因为这确实让我有机会深入研究数据库。

现在推荐的数据库结构是:

|----------|-----------|-----------|
|Session   |Student    |Project    |
|----------|-----------|-----------|
|1         |Stu1       |Proj_AA    |
|----------|-----------|-----------|
|1         |Stu2       |Proj_AB    |
|----------|-----------|-----------|
|1         |Stu3       |Proj_AC    |
|----------|-----------|-----------|
|2         |Stu1       |Proj_AB    |
|----------|-----------|-----------|
|2         |Stu2       |Proj_AA    |
|----------|-----------|-----------|
|2         |Stu3       |Proj_AC    |
|----------|-----------|-----------|
|3         |Stu1       |Proj_AB    |
|----------|-----------|-----------|
|3         |Stu2       |Proj_AC    |
|----------|-----------|-----------|
|3         |Stu3       |Proj_AA    |
|----------|-----------|-----------|

这里建议我将SessionStudent列作为复合键。这样我就可以为特定会话访问特定学生的特定记录。或者我只能为特定会话获得整个分配运行。

Questions:
这个想法是好的吗? 如何使用SQLAlchemy实现和查询复合键? 如果某个特定学生没有被分配项目,那么数据库会发生什么情况(如果他想要的所有项目都被采用,会发生什么)?在代码中,如果未为学生分配项目,而不是proj_id,则只需为该字段/对象获取None


我为提出多个问题而道歉,但由于这些问题密切相关,我以为我会在同一个地方问他们。


Edit - 25/03/2010

学生的班级结构目前如此:

class Student(DeptPerson):
    def __init__(self, name, stud_id):
        super(Student, self).__init__(name, stud_id)
        self.preferences = collections.defaultdict(set)
        self.allocated_project = None
        self.allocated_rank = 0

(杂项)它继承自一个名为DeptPerson的类,它只有namestud_id

因此,由于分配函数是针对学生(对于单个运行/试用/会话)分配的项目(由唯一ID引用 - Project是其自己的类),它将反映出的值allocated_project。如果学生没有为特定的跑步分配项目(因为其他人已经拥有它,那么......对不起),allocated_project仍为None(这对我来说非常有用)。

3 个答案:

答案 0 :(得分:3)

数据的二维显示是具有两个键的关系数据库表。

在您的示例中,学生密钥和会话密钥。

“复合键”是一段你可以忽略的噪音。没有用,也没有必要。复合键不能很好地解决任何问题并且会产生许多困难。假装你从未听过它。

我们所做的是引入一个带有简单“标识符”的附加列。这是他们排队的“自动生成,代理关键”。每行自动生成的唯一键是一件好事。复合键是一件坏事。

答案 1 :(得分:1)

您拥有的逻辑结构可以被视为Ternary Relationship,其中推荐给您的表对应于Attendance关系对象。因此,理想情况下,您还应该创建与此类似的对象模型:

Ternary relationship http://www.databasedesignstudio.com/faq/ternary-erd.jpg

现在,在你的情况下,如果每个Entity表只有一个字段,你可以争论为什么你需要多于1个表。但我仍然会这样建模,因为这个模型更好地代表了现实世界,你仍然需要存储Project学生喜欢的地方,这将是另一个与多对多关系的表格。 Student表。

使用实体更好,更容易理解sqlalchemy;而如果你只保留一张桌子,你真的会delve into the database多少?

关于composite keys:S.Lott给了你很好的理由避免使用它们,我完全赞同他对这个主题的看法。

答案 2 :(得分:0)

无法帮助你完成db的东西,因为我是一个全新的,只知道从sqlite表中查询数据......

但是,对于持久性,您可以使用pickle模块来存储对象吗?检查文档的确切用法,但我认为它几乎是文件(文件名,'wb')。write(pickle.pickle(myobject))写它和myobject = pickle.unpickle(文件(文件名,'rb')) )阅读。

然后你可以将多个表/任何内容读入多个变量并进行任何你想要的比较。

如果您不需要/想要通过Python阅读它,您也可以手动将其格式化为制表符分隔符或其他内容并将该文件加载到您选择的电子表格应用程序中(OpenOffice Calc非常棒)。 / p>