5

私はプログラミングにかなり慣れておらず、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")

辞書の出現を維持しながらそれを行う他の方法を私は本当に知りません。これは、それが誰の在庫であるかを知りたいので非常に重要です。これについて不明な点がある場合は、そのように言ってください。説明しようと思います

4

2 に答える 2

4

コードに論理エラーがあると思います。たとえば、各プレーヤーの在庫アイテムをinventory辞書に追加し、それを繰り返して他のアイテムを入力します。

ただし、辞書をリセットすることは決してないinventoryので、アイテムは蓄積され続けます(したがって、2番目のプレーヤーは自分のインベントリに加えて最初の人のインベントリを持っているように見えます)。

items少し後で使用している辞書にも同様の問題があります。emptyitems元々空のリストであったものにリセットしましたが、Pythonでの割り当ては参照によるものであるため、これは効果がありません(itemsすでにと同じオブジェクトでしたemptyitems)。

これらの2つの修正を使用すると、システムのすべてのメモリを使用しない可能性が高くなります。

別のその他のコードの改善(おそらくメモリ使用量とは関係ありません):

ループオーバーinventoryでは、同じ2つの値に繰り返しアクセスし、forを何にも使用していませんkeyfor key in inventory試す代わりにfor value1, value2 in inventory.itervalues()(またはin inventory.values()Python 3を使用している場合)。次にvalue1、の代わりに、inventory[key][0]およびvalue2の代わりに使用しますinventory[key][1](または、より適切な名前を付けます)。

編集:ループは次のようになります(以前はとにあった2つの値の名前を推測しています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)]
                )
于 2012-12-07T10:54:51.967 に答える
1

これはあなたのコードの問題を示していると思います:

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

つまり、リストへの参照をキャプチャしているため、emptyitems実際には非常に大きくなり続けます。これはおそらくあなたが意図したものではありません。非常に大きなリストを操作するには、非常にメモリを大量に消費することになると想像できます。

于 2012-12-07T10:52:00.127 に答える