我正在尝试处理一个3GB的XML文件,并在循环中获取一个内存错误,该循环读取文件并将一些数据存储在字典中。
class Node(object):
def __init__(self, osmid, latitude, longitude):
self.osmid = int(osmid)
self.latitude = float(latitude)
self.longitude = float(longitude)
self.count = 0
context = cElementTree.iterparse(raw_osm_file, events=("start", "end"))
context = iter(context)
event, root = context.next()
for event, elem in context:
if event == "end" and elem.tag == "node":
lat = float(elem.get('lat'))
lon = float(elem.get('lon'))
osm_id = int(elem.get('id'))
nodes[osm_id] = Node(osm_id, lat, lon)
root.clear()
我正在使用迭代解析方法,因此问题不在于读取文件。我只是想将数据存储在字典中以供以后处理,但似乎字典变得太大了。在程序的后面我读了链接,需要检查链接引用的节点是否在初始节点批次中,这就是我将它们存储在字典中的原因。
我怎样才能大大减少内存占用(脚本甚至没有接近完成,因此剃掉碎片并没有多大帮助)或者大大增加了python可用的内存量?监视内存使用情况看起来像python大约在1950 MB左右,而我的计算机仍有大约6 GB的可用内存。
答案 0 :(得分:3)
假设您创建了大量的Node
,您可以考虑使用__slots__
为每个Node
预定义一组固定的属性。这消除了存储每个实例__dict__
的开销(以防止创建未声明的属性),并且可以轻松地将每Node
的内存使用量减少~5倍(less on Python 3.3+ where shared key __dict__
reduces the per-instance memory cost for free )。
这很容易做到,只需将Node
的声明更改为:
class Node(object):
__slots__ = 'osmid', 'latitude', 'longitude', 'count'
def __init__(self, osmid, latitude, longitude):
self.osmid = int(osmid)
self.latitude = float(latitude)
self.longitude = float(longitude)
self.count = 0
例如,在Python 3.5上(共享密钥字典已经为您节省了一些东西),可以看到对象开销的差异:
>>> import sys
>>> ... define Node without __slots___
>>> n = Node(1,2,3)
>>> sys.getsizeof(n) + sys.getsizeof(n.__dict__)
248
>>> ... define Node with __slots__
>>> n = Node(1,2,3)
>>> sys.getsizeof(n) # It has no __dict__ now
72
请记住,这是带有共享密钥字典的Python 3.5;在Python 2中,__slots__
的每实例成本相似(一个指针大小的变量大于IIRC),而没有__slots__
的成本将增加几百个字节。
另外,假设您使用的是64位操作系统,请确保您已安装64位版本的Python以匹配64位操作系统;否则,Python将被限制在~2 GB的虚拟地址空间,而你的6 GB RAM数量非常少。