【问题标题】:Python dictionary eating up ramPython 字典吃掉了 ram
【发布时间】:2012-11-25 12:32:32
【问题描述】:

我对编程很陌生,并编写了一个程序来从 Team Fortress 2 玩家那里获取库存数据,并将库存项目放入字典中,其中 steamid 作为键,项目列表作为值。

我遇到的问题是,在字典中输入了大约 6000 条条目后,该程序基本上耗尽了我系统上的所有 RAM 并关闭了。

我猜字典只是变得太大了,但根据我从类似问题中读到的内容,包含 6000 个条目的字典不应该占用我那么多的 RAM。

我一直在寻找其他解决方案,但我可以为我的代码使用一些具体示例。

import re, urllib.request, urllib.error, gzip, io, json, socket, sys

with open("index_to_name.json", "r", encoding=("utf-8")) as fp:
    index_to_name=json.load(fp)

with open("index_to_quality.json", "r", encoding=("utf-8")) as fp:
    index_to_quality=json.load(fp)

with open("index_to_name_no_the.json", "r", encoding=("utf-8")) as fp:
    index_to_name_no_the=json.load(fp)

with open("steamprofiler.json", "r", encoding=("utf-8")) as fp:
    steamprofiler=json.load(fp)

inventory=dict()
playerinventories=dict()
c=0

for steamid in steamprofiler:
    emptyitems=[]
    items=emptyitems
    try:
        url=urllib.request.urlopen("http://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&steamid="+steamid+"&format=json")
        inv=json.loads(url.read().decode("utf-8"))
        url.close()
    except (urllib.error.HTTPError, urllib.error.URLError, socket.error) as e:
        c+=1
        print("URL/HTTP error, continuing")
        continue
    try:
        for r in inv["result"]["items"]:
            inventory[r["id"]]=r["quality"], r["defindex"]
    except KeyError:
        c+=1
        print(steamid, "didn't have an inventory")
        continue
    for key in inventory:
        try:
            if index_to_quality[str(inventory[key][0])]=="":
                items.append(
                    index_to_quality[str(inventory[key][0])]
                    +""+
                    index_to_name[str(inventory[key][1])]
                    )
            else:
                items.append(
                    index_to_quality[str(inventory[key][0])]
                    +" "+
                    index_to_name_no_the[str(inventory[key][1])]
                    )
        except KeyError:
            print("Key error, uppdate def_to_index")
            c+=1
            continue
playerinventories[int(steamid)]=items
items=emptyitems
c+=1
print(c, "inventories fetched")

我真的不知道有任何其他方法可以在保留字典外观的同时做到这一点,这非常重要,因为我希望能够知道它是谁的库存。如果我对此有任何不清楚的地方,请直说,我会尽力解释

【问题讨论】:

    标签: python dictionary ram steam


    【解决方案1】:

    我认为您的代码中有一些逻辑错误。例如,您将每个玩家的库存物品添加到 inventory 字典中,然后对其进行迭代以填充其他内容。

    但是,您永远不会重置 inventory 字典,因此它会继续积累物品(因此第二个玩家看起来除了拥有第一个人的物品栏外还拥有第一个人的物品栏)。

    您稍后使用的items 字典也有类似的问题。您将其重置为 emptyitems,它原本是一个空列表,但因为 Python 中的赋值是通过引用进行的,所以这不起作用(items 已经与 emptyitems 是同一个对象)。

    通过这两个修复,您可能有更好的机会不使用所有系统内存。

    另一个杂项代码改进(可能与内存使用无关):

    inventory 的循环中,您重复访问相同的两个值,而不是使用key 进行任何操作。而不是for key in inventory 尝试for value1, value2 in inventory.itervalues()(或者in inventory.values(),如果你使用的是Python 3)。然后用value1 代替inventory[key][0]value2 代替inventory[key][1](或者更好,给它们起更有意义的名字)。

    编辑:下面是循环的样子(我有点猜测之前在inventory[key][0]inventory[key][1] 中的两个值的名称):

    for quality, name in inventory.itervalues():
        try:
            if index_to_quality[str(quality)]=="":
                items.append(
                    index_to_quality[str(quality)]
                    +""+
                    index_to_name[str(name)]
                    )
            else:
                items.append(
                    index_to_quality[str(quality)]
                    +" "+
                    index_to_name_no_the[str(name)]
                    )
    

    【讨论】:

    • 所以添加:inventory=dict() items=list() 到“for steamid in steamprofiler”循环的开头应该在某种程度上防止内存占用?我不太明白库存循环的问题,库存中的键值对应于 index_to_name 和 index_to_quality 中的名称,您的解决方案如何做得更好?我不是在这里给嘴巴,我真的很好奇,因为我还很新。
    • 关于inventory 上的循环,我只是有点奇怪,您正在访问inventory[key][0]inventory[key][0] 而没有在其他任何地方访问key。如果这些是您需要使用的值(用于索引到您的其他字典),我建议您直接对它们进行循环迭代。如果inventory[key] 是两个元素的元组或列表,您可以在for 语句中将其解压缩为两个变量。我将编辑我的答案以显示它的外观,并带有适当的缩进。
    【解决方案2】:

    我相信这说明了您的代码存在问题:

    >>> emptyitems=[]
    >>> a=emptyitems
    >>> a.append("hello")
    >>> a.append("bar")
    >>> a
    ['hello', 'bar']
    >>> emptyitems
    ['hello', 'bar']
    

    换句话说,您正在捕获对emptyitems 列表的引用,该列表确实会不断增长。这可能不是您的意思,我可以想象处理一个非常大的列表会变得非常耗费内存。

    【讨论】:

    • 我认为我通过在 steamprofiler 循环中的 for steamid 开头添加 items=list() 解决了这个问题,干杯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 2021-03-12
    • 1970-01-01
    • 2011-08-28
    • 2012-12-20
    • 1970-01-01
    相关资源
    最近更新 更多