【发布时间】:2017-12-30 12:55:37
【问题描述】:
以下代码泄漏了我系统上的内存:
def test():
for u in users:
session.flush()
some_list = u.some_list
users 定义为
users = session.query(User).yield_per(500000)
some_list 在 User 模型中定义为
some_list = relationship("SomeThing", backref="user")
如您所见,运行session.flush() 不会释放已使用的内存。就此而言,循环末尾的del some_list 也没有。如果我删除 some_list = u.some_list 行,内存泄漏就会消失。
编辑:根据要求,这里是相关文件的完整代码。我认为它不会有太大帮助,因为我可以仅使用函数 test() 重现问题。
from redis import Redis
from pottery import RedisDict
import json
from anime_db import generate_session, User
redis = Redis.from_url('http://localhost:6379')
toshokan = RedisDict(redis=redis, key='toshokan')
session = generate_session(User)
users = session.query(User).yield_per(5000)
users = users[200000:]
def process():
c = 0
for u in users:
session.flush()
if c % 10000 == 0:
print('PROCESSED {} USERS'.format(c))
c += 1
al_db = u.animelist
name = u.name
if len(al_db) == 0 or name in toshokan:
continue
al = []
for a in al_db:
al.append((a.anime_id, a.status, a.num_watched, a.score))
toshokan[name] = json.dumps(al)
del al_db, name, al
def test():
c = 0
for u in users:
session.flush()
if c % 1000 == 0:
print('something')
c += 1
name = u.name
al_db = u.animelist
相关的数据库模型定义如下:
class AnimeEntry(Base):
__tablename__ = 'list_entries_anime'
uid = Column(Integer, Sequence('anime_list_entry_id_seq'), primary_key=True, autoincrement=True)
anime_id = Column(Integer, ForeignKey("anime.uid"), nullable=False)
user_id = Column(Integer, ForeignKey("users.uid"), nullable=False)
status = Column(Integer)
num_watched = Column(Integer)
score = Column(Integer)
added = Column(DateTime(timezone=True), default=func.now())
def __repr__(self):
return "<AnimeEntry(uid='%s', title='%s', user='%s')>" % (self.uid, self.anime_id, self.user_id)
class User(Base):
"""A user entry."""
__tablename__ = 'users'
uid = Column(Integer, Sequence('user_id_seq'), primary_key=True, autoincrement=True)
name = Column(String, unique=True)
joined = Column(DateTime(timezone=True), default=func.now())
animelist = relationship("AnimeEntry", backref="user")
编辑:停止循环不会停止内存使用,但之后运行 users = [] 会。所以这个问题与session.query(User).yield_per(5000)有关。
【问题讨论】:
-
为什么你认为
session.flush()会释放内存?为此,您需要session.expunge_all()。 -
我在其他地方被告知 flush() 可以工作;它没。就此而言,expunge_all() 也没有。
-
您如何观察到内存泄漏?你的其余代码是做什么的?
-
系统内存使用率稳步增长,不受控制。我正在运行的唯一代码是上述代码示例中的代码。中断该函数会清除内存。
-
我知道这个过程令人沮丧,但当我无法运行您的代码时,我试图猜测您的问题同样令人沮丧。自包含只是意味着我可以运行您的代码并重现您的问题。它确实不意味着只包含您认为可能导致问题的所有代码。你不能包括你的数据?包括一个可以重现您的问题的虚拟数据集。使用 PostgreSQL?看看它是否也能用 SQLite 重现。这些都是有价值的信息,如果您提供这些信息,您将获得更好的帮助。
标签: python memory-leaks sqlalchemy