我对编程非常陌生,并制作了一个程序来从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")
在保留字典外观时,我真的不知道有什么其他方法可以做到这一点,这非常重要,因为我希望能够分辨出它的库存。如果我不清楚这一点,那就说出来,我会试着解释
答案 0 :(得分:4)
我认为您的代码中存在一些逻辑错误。例如,您将每个玩家的库存物品添加到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)]
)
答案 1 :(得分:1)
我认为这说明了您的代码存在问题:
>>> emptyitems=[]
>>> a=emptyitems
>>> a.append("hello")
>>> a.append("bar")
>>> a
['hello', 'bar']
>>> emptyitems
['hello', 'bar']
换句话说,您正在捕获对emptyitems
列表的引用,该列表将继续增长非常大。这可能不是你的意思,而且我可以想象它会变得非常记忆强大而非常大的列表。