关于第二次传递.format()的Python KeyError

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于第二次传递.format()的Python KeyError相关的知识,希望对你有一定的参考价值。

我正在使用.format()来自动生成菜单。但是我还需要格式化它,因为用户运行更多测试来表明这些测试已经完成。

示例测试字典:

menuDict = {
    "1":
        {"testDataDict": "testDataDict1",
        "testName": "testName1",
        "testGroupName":"testGroupName1"},
    "2":
         {"testDataDict": "testDataDict2",
        "testName": "testName2",
        "testGroupName":"testGroupName2"
         },
    "3":
         {"testDataDict": "testDataDict3",
        "testName": "testName3",
        "testGroupName":"testGroupName3"
         },
     "4":
    {"testDataDict": "testDataDict4",
    "testName": "testName4",
    "testGroupName":"testGroupName3"
    }
    }

实际代码:

def menuAutoCreate(menuDict):
testGroupDict = {}
for testNum in menuDict.keys():
    try:
        testGroupDict[menuDict[testNum]["testGroupName"]].append(testNum)
    except:
        testGroupDict[menuDict[testNum]["testGroupName"]] = [testNum]
 #Groups the tests under the group names       

from natsort import natsorted as nt  
testGroupNamesList = nt(testGroupDict.keys(), key=lambda y: y.lower())
#Naturally sorts group names so they look orderly

textDump = " "
i = 0
while i < len(testGroupNamesList):
    howManyLinesEven = 0
    evenList = []
    howManyLinesOdd = 0
    oddList = []

    testGroupNameEven = testGroupNamesList[i]
    textDump += "|{:44}         |".format(testGroupNameEven)
    howManyLinesEven = len(testGroupDict[testGroupNameEven])

    evenList = nt(testGroupDict[testGroupNameEven], key=lambda y: y.lower())
    #If it's an even number, it puts the menu template on the left side of the screen


    if i != len(testGroupNamesList)-1:
        testGroupNameOdd = testGroupNamesList[i+1]
        textDump += "{:45}         |".format(testGroupNameOdd) + "
"
        howManyLinesOdd = len(testGroupDict[testGroupNameOdd])   
        oddList = nt(testGroupDict[testGroupNameOdd], key=lambda y: y.lower())
    #If it's odd, on the right side.  

    if i == len(testGroupNamesList)-1:
        textDump += "{:45}         |".format("") + "
"
        #Ensures everything is correctly whitespaced

    howManyLines = max(howManyLinesEven, howManyLinesOdd)
    #Checks how many lines there are, so if a group has less tests, it will have extra whitespaces

    for line in range(howManyLines):
        if line < howManyLinesEven:
            data = {"testNum": evenList[line], "testName": menuDict[evenList[line]]["testName"]}
            textDump += "|({d[testNum]}) {d[testName]:40}    {{doneTests[{d[testNum]!r}]:^8}} |".format(d=data)
        else:
            textDump += "|{:44}         |".format("")

        if line < howManyLinesOdd:
            data = {"testNum": oddList[line], "testName": menuDict[oddList[line]]["testName"]}
            textDump += "({d[testNum]}) {d[testName]:41}    {{doneTests[{d[testNum]!r}]:^8}} |".format(d=data) + "
"
        else:
            textDump += "{:45}         |".format("") + "
"
        #Automatically creates a menu

    i += 2

print(textDump)
print("
")

正如预期的那样输出:

|testGroupName1                                       |testGroupName2                                        |
|(1) testName1                    {doneTests['1']:^8} |(2) testName2                     {doneTests['2']:^8} |
|testGroupName3                                       |                                                      |
|(3) testName3                    {doneTests['3']:^8} |                                                      |
|(4) testName4                    {doneTests['4']:^8} |                                                      |                                                     |

最后一步将在其他地方完成,但放在这里进行演示:

    doneTests = {}
for testNum in menuDict.keys():
    doneTests[testNum] = "(-)"        
print(doneTests)

#textDump.format(**doneTests)
#This doesn't work for some reason?

textDump.format(doneTests = doneTests)

#This step will be repeated as the user does more tests, as an indicator of 
 which tests are completed. 

预期的输出是这样的:

|testGroupName1                                       |testGroupName2                                        |
|(1) testName1                    (-)                 |(2) testName2                     (-) |
|testGroupName3                                       |                                                      |
|(3) testName3                    (-) |                                                      |
|(4) testName4                    (-) |                                                      |                                                     |

但在这里它抛出:

KeyError: "'1'"

如果你删除!r:

{{doneTests[{d[testNum]!r}]:^8}}

它扔了一个

KeyError: 1 

代替。

我尝试用!s格式化。使用列表/元组。添加和删​​除括号。出于这个想法......

答案

试过你的例子。

我使用函数sorted()而不是natsorted()并添加了该行

textDump = ''

在行之前初始化textDump变量

i = 0

结果我没有错误并得到了预期的输出。

编辑

现在我重现了你的错误。我从!r中删除了{{doneTests[{d[testNum]!r}]:^8}}并在doneTests变量中使用了整数键

doneTests[int(testNum)] = "(-)"

解决问题。我想问题的根源是format()方法的工作原理。

以上是关于关于第二次传递.format()的Python KeyError的主要内容,如果未能解决你的问题,请参考以下文章

Python二级题一道,求解析

python基础5:字符格式化

关于CString 中format函数的问题

关于Python的TypeError not all arguments converted during string formatting

关于python中几个函数的用法

在 Python 3.5+ 中将格式字符串作为关键字参数传递的替代方法