【问题标题】:Dictionary changed size during iteration but I don't see where I've changed it字典在迭代期间改变了大小,但我没有看到我在哪里改变了它
【发布时间】:2013-12-23 02:48:23
【问题描述】:

我是 Python 新手,所以请耐心等待,但我尝试创建一个脚本,如果我还没有单词的同义词并以 JSON 格式将其添加到我的字典中。

p>

这是我的代码:

import json, sys, urllib
from urllib.request import urlopen

f = open('dict.json', 'r')
string = json.loads(f.read())
tempString = string
url = 'http://words.bighugelabs.com/api/2/myapicode/%s/json'

def main():
    crawl()

def crawl():
    for a in string:
        for b in string[a]:
            for c in string[a][b]:
                for d in string[a][b][c]:
                    if not isInDict(d):
                        addWord(d, getWord(url % d))
                    else:
                        print('[-] Ignoring ' + d)
    f.seek(0)
    f.write(tempString)
    f.truncate()
    f.close()

def isInDict(value):
    for x in list(tempString.keys()):
        if x == value:
            return True
    return False

def getWord(address):
    try:
        return urlopen(address).read().decode('utf-8')
    except:
        print('[!] Failed to get ' + address)
    return ''

def addWord(word, content):
    if content != None and content != '':
        print('[+] Adding ' + word)
        tempString[word] = content
    else:
        print('[!] Ignoring ' + word + ': content empty')

if __name__ == '__main__':
    main()

在运行时,它运行良好,直到“amour”,它给了我这个:

working fine
[+] Adding sex activity
[+] Adding sexual activity
[+] Adding sexual desire
[+] Adding sexual practice
[-] Ignoring amour
Traceback (most recent call last):
  File "crawler.py", line 47, in <module>
    main()
  File "crawler.py", line 10, in main
    crawl()
  File "crawler.py", line 13, in crawl
    for a in string:
RuntimeError: dictionary changed size during iteration

但我没有看到我在 string 上的任何地方进行了更改,只有 tempString...

PS:如果你想要我读到的 JSON 数据:

{
    "love": {
        "noun": {
            "syn": ["passion", "beloved", "dear", "dearest", "honey", "sexual love", "erotic love", "lovemaking", "making love", "love life", "concupiscence", "emotion", "eros", "loved one", "lover", "object", "physical attraction", "score", "sex", "sex activity", "sexual activity", "sexual desire", "sexual practice"],
            "ant": ["hate"],
            "usr": ["amour"]
        },
        "verb": {
            "syn": ["love", "enjoy", "roll in the hay", "make out", "make love", "sleep with", "get laid", "have sex", "know", "do it", "be intimate", "have intercourse", "have it away", "have it off", "screw", "jazz", "eff", "hump", "lie with", "bed", "have a go at it", "bang", "get it on", "bonk", "copulate", "couple", "like", "mate", "pair"],
            "ant": ["hate"]
        }
    }
}

【问题讨论】:

  • 不是问题的原因,但是你的isInDict()函数可以简化为return value in tempString
  • @MartijnPieters 谢谢!

标签: python json python-3.x dictionary


【解决方案1】:

举个例子:

>>> for i in d:
...     if d[i] == 2:
...         d.pop(i)
...
2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

要解决此问题,请执行以下操作:

>>> for i in d.keys():
...     if d[i] == 2:
...         d.pop(i)
...
>>> d
{'one': 1}

所以,对于您的特定代码:

尝试改变这个:

def crawl():
    for a in string:

到:

def crawl():
    for a in string.keys():

如果这不起作用,我将在今天晚些时候更深入地查看您的代码。

【讨论】:

    【解决方案2】:

    在这一行:

    string = json.loads(f.read())
    tempString = string
    

    您指定tempString 来引用与string 相同的字典对象。然后,在addWord 中更改tempString

        tempString[word] = content
    

    因为 tempString 只是对与 string 相同的字典对象的另一个引用,所以 string 也会发生变化。

    为避免这种情况,请使用:

    import copy
    tempString = copy.deepcopy(string)
    

    此外,使用像string 这样的变量名称通常是一种不好的做法,这些变量名称也是内置函数的名称。它的描述性不是很好,而且它会让你在名称在范围内时无法方便地访问内置函数。

    【讨论】:

    • 更何况 tempString 和 string 都不是字符串!
    • 谢谢,你把我引向了正确的方向 :) 另外,感谢大家提供的所有小技巧,我知道它不是一个字符串等等,这完成得非常快而且非常混乱,这只是为了生成“父”项目所需的“同义词词典”,不过谢谢!
    猜你喜欢
    • 1970-01-01
    • 2015-03-31
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多