python – SQLAlchemy吃RAM

前端之家收集整理的这篇文章主要介绍了python – SQLAlchemy吃RAM前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试使用 Python处理它后将一些XML数据导入我的MysqL数据库.为了简单起见,我在一个使用sqlAlchemy访问我的数据库的脚本中完成所有操作.

XML文件有大约80,000个条目,我使用xml.etree.cElementTree的iterparse方法处理它,并在使用它们之后删除节点以使我的内存使用量保持在20mb左右.

一旦我包含sqlAlchemy并开始向数据库添加内容,我的内存使用量每秒增加大约10mb,直到脚本耗尽了我的所有内存并且操作系统将其杀死.

这基本上是我的代码的样子:

  1. index = 0
  2.  
  3. for element in iterate_xml():
  4. ...
  5.  
  6. index += 1
  7.  
  8. session.add(Model(**data))
  9.  
  10. if index % 1000 == 0:
  11. session.flush()
  12. session.commit()

我不知道还有什么可以尝试的.定期的.flush()和.commit()确实有所帮助,但它们无法解决问题.

sqlAlchemy不适合执行此任务吗?

我像这样设置sqlAlchemy:

  1. Base = declarative_base()
  2. engine = create_engine(config.sqlALCHEMY_DATABASE_URI,echo=False)
  3.  
  4. Session = sessionmaker(bind=engine,autoflush=False,expire_on_commit=False)
  5. session = Session()

我的表看起来像这样:

  1. columns = []
  2.  
  3. for name,datatype in structure.iteritems():
  4. if isinstance(datatype,int):
  5. datatype = String(datatype or 20)
  6.  
  7. column = Column(name,datatype)
  8. columns.append(column)
  9.  
  10. Metadata = MetaData(bind=engine)
  11. table = Table('table_name',Metadata,Column('id',Integer,primary_key=True),*columns
  12. )
  13.  
  14. Metadata.drop_all(engine)
  15. Metadata.create_all(engine)
  16.  
  17. class MyTable(Base):
  18. __tablename__ = 'table_name'
  19. __table_args__ = {
  20. 'autoload': True,'autoload_with': engine
  21. }

structure是一个将列名映射到数据类型的字典(它是从XML生成的):

  1. structure = {
  2. 'column_name': sqlAlchemyDataType,...
  3. }

解决方法

这是代码sqlAlchemy版本.在0.7和0.8的测试中,它不泄漏任何内存,这对我来说并不意外,因为我们在持续集成下进行了十几次测试,以确保在许多情况下没有任何泄漏.因此,第一步是确认此脚本不会泄漏,然后尝试找出此脚本与您之间的更改,以生成实际显示泄漏内存的测试用例.
  1. from sqlalchemy import Column,String,create_engine
  2. from sqlalchemy.orm import Session
  3. from sqlalchemy.ext.declarative import declarative_base
  4.  
  5. Base = declarative_base()
  6.  
  7. class Model(Base):
  8. __tablename__ = "a"
  9.  
  10. id = Column(Integer,primary_key=True)
  11. data = Column(String)
  12.  
  13. e = create_engine("sqlite:///somefile.db")
  14.  
  15. Base.Metadata.create_all(e)
  16.  
  17. session = Session(e)
  18.  
  19. for index in xrange(10000000):
  20. session.add(Model(data="data %d" % index))
  21.  
  22. if index % 1000 == 0:
  23. print "flushing... %d" % index
  24. session.flush()
  25. session.commit()

当然,重要的是要注意sqlAlchemy过去泄露内存的那些问题.这是最近修复的泄漏历史:

0.7.8 – 最近的.此处修复的泄漏仅在以下情况下发生:1.C扩展,2.pyodbc驱动程序,在某些结果获取操作期间(并非所有这些操作)

0.6.6 – C扩展中的“十进制”结果处理器有泄漏.

0.6.6 – 如果用于以某种方式选择行,则sqlSoup扩展被识别为具有潜在泄漏(sqlSoup现在是它自己的项目)

0.5.5 – 当对象被打开并放回会话时固定潜在的内存泄漏

0.5.4 – 对会话的内存使用进行了重大改进.你肯定想要超越这个版本.

猜你在找的Python相关文章