Python KeyError при втором прохождении .format () - PullRequest
0 голосов
/ 06 сентября 2018

Я использую .format () для автоматического создания меню. Но мне также нужно отформатировать его, так как пользователи запускают больше тестов, чтобы показать, что эти тесты уже выполнены.

Пример теста dict:

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) + "\n"
        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("") + "\n"
        #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) + "\n"
        else:
            textDump += "{:45}         |".format("") + "\n"
        #Automatically creates a menu

    i += 2

print(textDump)
print("\n")

Вывод этого, как и ожидалось:

|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. Использование списков / кортежей. Добавление и удаление скобок. На данный момент нет идей ...

1 Ответ

0 голосов
/ 06 сентября 2018

Только что попробовал ваш пример.

Я использовал функцию sorted() вместо natsorted() и добавил строку

textDump = ''

для инициализации переменной textDump перед строкой

i = 0

В результате я не получил ошибок и получил ожидаемый результат.

EDIT

Теперь я воспроизвел вашу ошибку. Я удалил !r из {{doneTests[{d[testNum]!r}]:^8}} и использовал целочисленные ключи в doneTests переменная

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

для решения проблемы. Я думаю, причина проблемы в том, как работает метод format().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...