2012-12-07 3 views
5

저는 프로그래밍에 익숙하지 않고 Team Fortress 2 플레이어에서 인벤토리 데이터를 가져 와서 그 목록으로 키우기와 항목 목록을 값으로 사용하는 사전에 인벤토리 항목을 가져 오는 프로그램을 만들었습니다 .파이썬 사전 먹기 ram

내가 겪고있는 문제는 사전에 약 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") 

는 정말 내가 누구의 재고 그것이 말할 수 있도록하고 싶습니다으로 매우 중요하다 사전 성상을 유지하면서 그것을 할 다른 방법을 알고하지 않습니다. 당신이 캡처하고 즉

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

:이 모든에 불분명 한 경우, 그냥이 코드에 문제를 보여 믿고 그렇게 말 나는

답변

4

코드에 논리 오류가 있다고 생각합니다. 예를 들어 각 플레이어의 인벤토리 항목을 inventory 사전에 추가 한 다음 다른 플레이어의 인벤토리 항목을 반복하여 다른 항목을 채 웁니다.

그러나 사전에 inventory 사전을 재설정하지 않으므로 항목이 계속 누적되므로 두 번째 플레이어는 자신의 인벤토리를 추가로 보유하게됩니다.

조금 나중에 사용하는 items 사전과 비슷한 문제가 있습니다. 원래 빈 목록이었던 emptyitems으로 다시 설정했지만 파이썬에서의 할당은 참조에 의한 것이므로 아무런 효과가 없습니다 (items은 이미 emptyitems과 같은 개체였습니다).

두 가지 픽스를 사용하면 모든 시스템 메모리를 사용하지 않는 것이 더 좋습니다.

(아마도 메모리 사용과 관련이없는) 다른 기타 코드 개선 : inventory 이상 루프에서

, 당신은 반복적으로 동일한 두 개의 값을 액세스하고 아무것도에 대한 key를 사용하지 않는. for key in inventory 대신 for value1, value2 in inventory.itervalues() (또는 in inventory.values() 파이썬 3을 사용하는 경우)을 시도하십시오. 그런 다음 inventory[key][0]value2 대신 value1을 사용하고 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)] 
       ) 
+0

이렇게 추가하면 : "steamprofiler의 steamid"루프의 시작 부분에 inventory = dict() items = list() 의 시작 부분에 메모리 hogging을 방지해야합니다. 어느 정도? 인벤토리 루프의 문제를 잘 이해하지 못하고 있습니다. 인벤토리의 주요 값은 index_to_name 및 index_to_quality의 이름과 일치합니다. 어떻게 솔루션을 개선 할 수 있습니까? 나는 여기 입을 대지 않고있어, 내가 상당히 새로운 것에 대해서 진정으로 궁금해. – Tenbin

+0

'inventory' 이상의 루프와 관련해서는'inventory [key] [0]'과'inventory [key] [0]'에 접근하고 다른 곳에서는'key '에 접근하지 않는 것이 이상한 일이었습니다. 만약 당신이 (당신의 다른 사전에 색인을 붙이기 위해) 사용할 필요가있는 값이라면, 나는 당신이 루프를 반복하도록 제안한다. 'inventory [key]'가 두 개의 원소 튜플이나리스트라면'for' 문에서 두 개의 변수로 압축을 풀 수 있습니다. 적절한 답장으로 내 대답을 편집 해 보겠습니다. – Blckknght

1

을 설명하려고합니다 emptyitems 목록에 대한 참조는 실제로 계속 커질 것입니다. 이것은 아마도 당신이 의미 한 바가 아니며 매우 큰 목록을 저글링하는 것이 아주 기억에 남을 것이라고 상상할 수 있습니다.

+0

내가 고정 된 생각 : 여기에 루프 (I 일종의 두 inventory[key][0] 이전에 있었다 값과 inventory[key][1]의 이름에서 추측하고있어) 보일 수 있습니다 방법 steamprofiler 루프의 steamid에 대한 시작 부분에 list()를 추가합니다. – Tenbin