代码之家  ›  专栏  ›  技术社区  ›  habet

sqlalchemy通过resultproxy对象更新值

  •  -1
  • habet  · 技术社区  · 7 年前

    我有一个包含大量文本数据的大表。下面的代码片段是一个来自大型 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. 
    

    我读到,这种分配行的方式在 sqlalchemy 0.9或其他版本之前的版本。(我有1.2.0,但降级似乎是一个愚蠢的选择,因为一定有办法做到这一点。)

    我知道这种基于查询结果分配给单行的方法在 sqlsoup ,但宁愿不使用其他包,因为确实有一种方法可以从 SQL炼金术

    我的问题:

    我该怎么做 row.processed_text = result 要获得所需的单行更新,请继续?

    由于这应该适用于不同的数据库,列的名称可能不同,因此我希望避免硬编码 Query(data_table).where(data_table.primary_key == row.primary_key).update() 因为我不一定知道主键列的名称。

    注:这里的重点不是数据库的性能,因为我有时间,所以这应该很少运行,而且 computationally_heavy() 无论如何,这会耗费大量时间。

    另外,我是社会科学家,不是程序员,很抱歉,如果这是一个非常愚蠢的问题。。。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Ilja Everilä    7 年前

    你好像混在一起了 Core 以及 ORM .模型实例通过以下方式跟踪对属性的更改 instrumentation .而不仅仅是 Table 使用表定义声明性类:

    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相同的方式跟踪变化。