2012-12-07 17 views
5

Ich bin ziemlich neu zu programmieren und machte ein Programm, um Inventardaten von Team Fortress 2 Spielern zu holen und die Inventargegenstände in ein Wörterbuch mit dem steamid als der Schlüssel und der Liste der Einzelteile als der Wert zu setzen .Python-Wörterbuch Essen ram

Das Problem, auf das ich gestoßen bin, ist, dass nach ungefähr 6000 Einträgen in das Wörterbuch das Programm im Wesentlichen den gesamten RAM auf meinem System aufgesaugt hat und heruntergefahren wird.

Ich nehme an, das Wörterbuch wird einfach zu groß, aber nach dem, was ich von ähnlichen Fragen gelesen habe, sollte ein Diktat von 6000 Einträgen nicht so viel von meinem RAM aufnehmen.

Ich habe nach anderen Lösungen gesucht, aber ich könnte einige konkrete Beispiele für meinen Code verwenden.

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

Ich weiß nicht wirklich irgendeinen anderen Weg, es zu tun, während das Wörterbuch appearence beibehalten, was ganz wichtig ist, wie ich möchte in der Lage sein, dessen Inventars zu sagen, es ist. Wenn ich in irgendetwas davon unklar waren, sagen Sie einfach so, und ich werde versuchen,

Antwort

4

Ich denke, Sie haben einige logische Fehler in Ihrem Code. Zum Beispiel fügen Sie die Inventargegenstände jedes Spielers zum inventory Wörterbuch hinzu und durchlaufen es dann, um andere Sachen zu füllen.

Sie setzen jedoch nie das inventory Wörterbuch zurück, so dass es fortfährt, Elemente zu akkumulieren (so wird der zweite Spieler das Inventar der ersten Person zusätzlich zu ihrem eigenen haben).

Sie haben ein ähnliches Problem mit dem items Wörterbuch, das Sie später verwenden. Sie haben es auf emptyitems zurückgesetzt, was ursprünglich eine leere Liste war, aber da die Zuweisung in Python per Verweis erfolgt, hat dies keine Auswirkung (items war bereits das gleiche Objekt wie emptyitems).

Mit diesen beiden Fixes haben Sie möglicherweise eine bessere Chance, nicht den gesamten Speicher Ihres Systems zu nutzen.

Eine weitere verschiedene Code Verbesserung (wahrscheinlich auf der Speichernutzung nicht verwandt):

In der Schleife über inventory, sind Sie immer wieder die gleichen zwei Werte zugreifen und nicht die key für alles verwenden. Anstatt for key in inventory versuchen Sie for value1, value2 in inventory.itervalues() (oder in inventory.values(), wenn Sie Python 3 verwenden). Verwenden Sie dann anstelle von inventory[key][0] und value2 statt inventory[key][1]value1 (oder besser, geben Sie ihnen sinnvollere Namen).

bearbeiten: Hier ist, wie die Schleife aussehen könnte (ich irgendwie bin für die beiden Werte bei Namen zu erraten, die in inventory[key][0] und inventory[key][1] vorher waren):

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)] 
       ) 
+0

Also: inventory = dict() items = list() an den start der "für steamid in steamprofiler" schleife sollte die memory hogging zu verhindern einem gewissen Grad? Ich verstehe das Problem mit der Inventarisierungsschleife nicht ganz, die Schlüsselwerte im Inventar entsprechen den Namen in index_to_name und index_to_quality. Wie verbessert Ihre Lösung das? Ich gebe hier keinen Mund, ich bin wirklich neugierig, da ich ziemlich neu bin. – Tenbin

+0

In Bezug auf die Schleife über 'Inventar', ich war nur ein bisschen seltsam, dass Sie auf 'Inventar [Schlüssel] [0]' und 'Inventar [Schlüssel] [0] 'zugreifen und nirgendwo anders' Schlüssel' zugreifen. Wenn dies die Werte sind, die Sie verwenden müssen (um sie in Ihre anderen Wörterbücher zu indizieren), schlage ich vor, dass Sie die Schleife direkt auf ihnen durchlaufen lassen. Wenn 'inventory [key] 'ein Tupel oder eine Liste mit zwei Elementen ist, können Sie es in zwei Variablen direkt in der' for'-Anweisung entpacken. Ich werde meine Antwort bearbeiten, um zu zeigen, wie das aussehen würde, mit richtiger Einrückung. – Blckknght

1

zu erklären, ich glaube, das ist ein Problem mit dem Code zeigt:

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

Mit anderen Worten: Sie erfassen ein Verweis auf die emptyitems Liste, die in der Tat sehr groß wachsen wird. Das ist wahrscheinlich nicht das, was Sie meinten, und ich kann mir vorstellen, dass es ziemlich speicherintensiv wird, eine sehr große Liste zu jonglieren.

+0

denke ich festgelegt, dass durch Hinzufügen von Elementen = list() an den Anfang der für steamid in steamprofiler loop, cheers – Tenbin