简体   繁体   English

Python字典吃掉了ram

[英]Python dictionary eating up ram

I'm pretty new to programming and made a program to fetch inventory data from Team Fortress 2 players and put the inventory items into a dictionary with the steamid as the key and the list of items as the value. 我对编程很陌生,并且制作了一个程序来从Team Fortress 2玩家那里获取库存数据,并将库存物品放入字典中,以Steamid作为键,并将物品清单作为值。

The problem I'm running into is that after about 6000 entries into the dictionary the program has sucked up essentially all of the RAM on my system and shuts down. 我遇到的问题是,在字典中输入了约6000个条目后,程序实际上已占用了系统上的所有RAM并关闭了。

I'm guessing the dictionary simply becomes too large but by what I've read from similar questions a dict of 6000 entries shouldn't take up that much of my RAM. 我猜字典简直太大了,但是从我从类似问题中读到的内容,字典中有6000条记录应该不会占用我太多的RAM。

I've been looking into other solutions but I could use some concrete examples for my code. 我一直在寻找其他解决方案,但是我可以在代码中使用一些具体示例。

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")

I don't really know of any other way to do it while retaining the dictionary appearence, which is quite important as I'd like to be able to tell whose inventory it is. 我真的不知道在保留字典外观的情况下还有其他方法可以这样做,这非常重要,因为我想知道它是谁的清单。 If I've been unclear in any of this, just say so and I'll try to explain 如果我不清楚其中的任何一个,那就这么说,我会尽力解释

I think you have some logic errors in your code. 我认为您的代码中存在一些逻辑错误。 For instance, you're adding each player's inventory items to the inventory dictionary, then iterating over it to fill in other stuff. 例如,您要将每个玩家的库存物品添加到inventory字典中,然后对其进行迭代以填充其他内容。

However, you're never resetting the inventory dictionary, so it continues to accumulate items (so the second player will appear to have the first person's inventory in addition to their own). 但是,您永远不会重置inventory字典,因此它将继续累积物品(因此,第二位玩家似乎除了拥有第一人的库存外,还会拥有第一人的库存)。

You've got a similar issue with the items dictionary that you're using a bit later on. 稍后使用的items字典也有类似的问题。 You reset it to emptyitems which was originally an empty list, but because assignment in Python is by reference, this has no effect ( items was already the same object as emptyitems ). 您将其重置为本来是空列表的emptyitems ,但是由于Python中的赋值是通过引用进行的,因此没有任何效果( items已经与emptyitems是同一对象)。

With those two fixes you may have a better chance at not using all your system's memory. 有了这两个修复程序,您可能有更大的机会不使用系统的所有内存。

Another miscellaneous code improvement (probably not related to memory usage): 另一个其他代码改进(可能与内存使用无关):

In your loop over inventory , you're repeatedly accessing the same two values and not using the key for anything. inventory ,您反复访问相同的两个值,而不使用任何key Instead of for key in inventory try for value1, value2 in inventory.itervalues() (or in inventory.values() if you're using Python 3). 除了在for key in inventory尝试for value1, value2 in inventory.itervalues() (或者in inventory.values()使用Python 3的情况下for value1, value2 in inventory.itervalues()尝试for value1, value2 in inventory.itervalues() Then use value1 in place of inventory[key][0] and value2 in place of inventory[key][1] (or even better, give them more meaningful names). 然后使用value1代替inventory[key][0]并使用value2代替inventory[key][1] (甚至更好,为它们提供更有意义的名称)。

Edit : Here's how the loop might look (I'm sort of guessing at names for the two values that were previously in inventory[key][0] and 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)]
                )

I believe this illustrates a problem with your code: 我相信这说明了您的代码存在问题:

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

In other words, you're capturing a reference to the emptyitems list, which will keep growing very large indeed. 换句话说,您正在捕获对emptyitems列表的引用,该列表确实会变得非常大。 This is probably not what you meant, and I can imagine it becoming quite memory-intense to juggle a very large list. 这可能不是您的意思,并且我可以想象要处理大量列表会变得非常占用内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM