問題は解決されませんでしたが、次の存在が原因でした:
def __del__(self):
print "deleted!"
モデルクラスで。モデルクラスから削除するとすぐに、メモリ使用量の問題を実験できなくなりました。
アドホック セッション/エンジンで使用しているいくつかのモデルがあり、これは正常に動作していますが、データベース/セッション コンテキストの外部でこれらのオブジェクトを作成したい場合、SQLAlchemy インストルメンテーションがオブジェクトの参照を保持しているようです。削除されることはありません。
私がやりたいのは、「通常の」Pythonオブジェクトのようなモデルオブジェクトを作成し、それをセッション/データベースに追加しないことです(ただし、他のコンテキストではデータベースに追加する必要があります)。これは間違っていますか?
import gc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String
base = declarative_base()
class SomeObject(base):
__tablename__ = "SomeObject"
instrumented_name = Column('name', String(55), primary_key=True)
uninstrumented_name = None
def __del__(self):
print "deleted!"
obj1 = SomeObject()
obj1.uninstrumented_name = "foo"
obj1 = None
#obj1 is properly deleted
obj2 = SomeObject()
obj2.instrumented_name = "bar"
obj2 = None
gc.collect()
#obj2 never deleted
編集私はいくつかの追加のテストを行いましたが、オブジェクトがセッションにコミットされない場合 (ロールバックなど)、SQLAlchemy がメモリ リークを引き起こすようです。
インストルメント化されたオブジェクトの参照を SQLAlchemy に強制的に解放させる方法はありますか?
import gc
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, create_engine
Base = declarative_base()
class MemoryMonster(Base):
__tablename__ = "MemoryMonster"
_id = Column('id', Integer(), primary_key=True)
_name = Column('name', String(55))
def __init__(self):
self._name = "some monster name"
self._eat_some_ram = ' ' * 1048576
def __del__(self):
print "deleted!"
engine = create_engine("sqlite:///:memory:")
session_factory = sessionmaker(engine)
Session = scoped_session(session_factory)
Base.metadata.create_all(engine)
def create_and_commit():
session = Session()
for _ in range(100):
session.add(MemoryMonster())
session.commit()
Session.remove()
gc.collect()
def create_and_rollback():
session = Session()
for _ in range(100):
monster = MemoryMonster()
session.add(monster)
session.expunge(monster)
session.rollback()
Session.remove()
gc.collect()
def create_do_not_include_in_session():
session = Session()
for _ in range(100):
monster = MemoryMonster()
session.rollback()
Session.remove()
gc.collect()
# Scenario 1 - Objects included in the session and commited
# No memory leak
create_and_commit()
# Scenario 2 - Objects included in the session and rollbacked
# Memory leak
create_and_rollback()
# Scenario 3 - Objects are not not included in the session
# Memory leak
create_do_not_include_in_session()