在SQLalchemy中可以使用namedtuple吗?

2024-10-02 00:40:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直试图让一个namedtuple与SQLalchemy一起工作,但是没有用。。网络搜索并不是很有启发性,而且我是Python和SQLalchemy的新手,所以我不太确定自己是不是在追逐风车:(基本的想法是我有一个名为dtuple,即:

Point=namedtuple('Point',['x','y'])

它基本上创建了一个类点(tuple),如果我是正确的。一开始效果很好,我可以创建如下对象:

^{pr2}$

但是在我创建引擎etc并调用mapper之后,我无法创建更多的对象而不会出现以下错误:

Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    f=Point(3,4)
TypeError: __init__() takes exactly 1 argument (3 given)

你知道为什么会这样吗?有人知道如何使用sqlalchemy让namedtuple工作吗?当然,我可以定义我自己的Point类,但我现在正沉迷于让namedtuple工作。。 我使用的是python2.7,SQLalchemy 0.6.6(sqlite引擎)

示例:

我在尝试这样的事情:

from sqlalchemy import *
from sqlalchemy.orm import *
from collections import namedtuple

Point=namedtuple('Point',['x','y'],verbose=True)
p=Point(3,4)


db=create_engine('sqlite:///pointtest.db')
metadata=MetaData()
pointxy=Table('pointxy',metadata,
              Column('no',Integer,primary_key=True),
              Column('x',Integer),
              Column('y',Integer),
              sqlite_autoincrement=True)
metadata.create_all(db)
m=mapper(Point, pointxy)
Session=sessionmaker(bind=db)
session=Session()
f=Point(3,4)

主要的想法是我想要一个可以很容易地存储在数据库中的命名集合。所以这个:

class Bunch:
    __init__ = lambda self, **kw: setattr(self, '__dict__', kw)

不会和sqlalchemy一起工作(我想)。我可以创建一个Bunch类,但我事先不知道要在我的集合中存储多少个int。。我会在创建数据库之前设置它。我希望我说得通。。在


Tags: 对象from引擎importtruedbsqlitesqlalchemy
2条回答

映射器似乎添加了一个<init方法。因此,在mapper语句之后执行以下操作可以使其再次工作:

del Point.__init__

我不确定在这种类型的事情上使用映射器是不是正确的主意。mapper很可能需要主键(“no”)才能正常工作,而nametuple当前没有足够的空间。在

Namedtuples有一系列的行为使得它们不适合使用sqlalchemy进行映射:最重要的是,Namedtuples在创建之后不能被更改。这意味着您不能在insert操作之后使用namedtuple来跟踪数据库中一行的状态。您通常希望执行以下操作:

class MyDataHolder(namedtuple('MyDataHolder', ('id', 'my_value')):
    pass

mapper(MyDataHolder, MyDataMeta)

...

newRow = MyDataHolder(None, 'AAA')

...

session.add(newRow)

当会话代码执行SQL以将新数据添加到数据库时,它需要更新newRow,以便新行.id对应于数据库分配给行的id。但是由于newRow是一个不可变的元组,因此不能更改id来保存从数据库返回的主键。这使得namedtuples在很大程度上不适合映射器。在

发生此问题是因为namedtuple在\uu new\uu中初始化,然后不希望更改。__在对象被创建之后,init_uUi()会被调用,因此没有任何效果。因此,namedtuples的qinit_uu只定义了一个参数:self。我猜映射器假设优init_uUu()正在处理类初始化,而不知道新的和不可变的类型。看起来他们在用创建时传递的参数调用类名。您可以通过指定自己的初始值设定项来“修复”这个问题,但最终会出现weakref问题。在

weakref错误的发生是因为namedtuples使用u slot_uuu存储它们的值,而不是可变的u dict_uus。我知道使用uu slots_uuu是一种内存优化,因此可以高效地存储大量的namedtuples。我假设一个namedtuple在创建之后不会改变。这包括添加属性,因此使用插槽是一个值得优化的内存。但是,我并不理解为什么namedtuple类的作者不支持弱引用。这不会是特别困难的,但可能有一个很好的原因,我失踪。在

今天早上我遇到了这个问题,并通过定义自己的类来解决这个问题,该类是用一个_fieldset属性初始化的。这指定了我感兴趣的(子)字段集。然后,我花了一些时间阅读了namedtuples是如何与其他一些python内部构件一起实现的文档。我想我已经了解了为什么这不起作用了,但是我相信有一些python专家比我更了解这一点。在

克里斯

相关问题 更多 >

    热门问题