我有一张包含大量文字数据的大表。下面的代码片段是我正在撰写的较大textcorpus-reader
的最小示例。
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///corpus.db")
meta = MetaData(bind=engine)
Session = sessionmaker(bind=engine, autoflush=False, expire_on_commit=False, autocommit=False)
data_table = Table("data", meta, autoload=True, autoload_with=engine)
def computationally_heavy(raw_text):
"""
This does a lot of text-processing and needs a lot of RAM and CPU.
For the sake of this example it does just this:
"""
return raw_text.split("\n")
session = Session()
query = session.query(data_table).yield_every(10)
for i, row in enumerate(query):
result = computationally_heavy(row.raw_text)
# This is, what is not working - column 'processed_text' does already exist:
row.processed_text = result
if i % 250 == 0:
s.flush()
session.commit()
session.close()
我的问题是我想更新for
循环中的单行,但我得到:
AttributeError: can't set attribute.
我读到在0.9之前的sqlalchemy
版本中可以使用这种分配行的方式。 (我有1.2.0,但降级似乎是一个愚蠢的选择,因为必须有一种方法来做到这一点。)
我知道这种基于查询结果分配给单行的方式可以在sqlsoup
中使用,但宁愿不使用另一个包,因为肯定有办法从sqlalchemy
执行此操作。
我的问题:
我如何执行row.processed_text = result
以获得所需的单行更新?
由于这应该适用于不同的数据库,其中列的名称可能不同,我希望避免使用硬编码的Query(data_table).where(data_table.primary_key == row.primary_key).update()
,因为我不一定知道主键列的名称。
computationally_heavy()
无论如何都要消耗很多时间。
我也是社会科学家,而不是程序员,很抱歉,如果这是一个非常愚蠢的问题......
答案 0 :(得分:1)
好像你混合了Core和ORM。模型实例通过instrumentation跟踪属性的更改。而不只是Table
定义一个Declarative类,使用你的表:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base(metadata=meta)
class DataTable(Base):
__table__ = Table("data", meta, autoload=True, autoload_with=engine)
在查询中使用它,生成的模型对象将跟踪其属性的更改:
query = session.query(DataTable).yield_every(10)
我读到这种分配行的方式可以在0.9之前的sqlalchemy版本中使用。 (我有1.2.0,但降级似乎是一个愚蠢的选择,因为必须有一种方法来做到这一点。)
结果元组可分配的原因是issue和was fixed in version 1.0.5。这并不意味着他们以与ORM相同的方式跟踪变化。