Programming new key error

Заказал на АлиЭкспрессе десяток ключей, типа перепрограммируемые. Никак не получается их перепрограммировать. Пробовал разные исходники, н в какую! Читать читает, а писать выдает ошибку и снова показывает старый ключ. Может кто уже наступал на эти грабли? Помогите!

MaximZ

Offline

Зарегистрирован: 24.03.2015

У меня ключевым моментом оказался резистор на 220 Ом при напряжении в 5 Вольт. Обязательно нужно скачать другую библиотеку OneWire

Попробуй разные варианты с резистором.

Ссылка https://yadi.sk/d/Eiqc1MWYmdQh3
Оттуда берешь библиотеку и заменяешь стандартную, которая вместе с IDE идет (это важно).

Вот мой скетч
 

/* 
 * тестируем работу по 1-Wire с ключём-таблеткой DS1990A
 */
 
#include <OneWire.h>

#define pin 10

byte key_to_write[] = { 0x01, 0x81, 0xBB, 0xB8, 0x0B, 0x00, 0x00, 0x93 };      

OneWire  ds(pin);  // pin 10 is 1-Wire interface pin now

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte data[8];

  delay(1000); // 1 sec
  
  ds.reset();
  delay(50);
  ds.write(0x33); // "READ" command
  
  ds.read_bytes(data, 8);

  Serial.print("KEY ");
  for( i = 0; i < 8; i++) {
    Serial.print(data[i], HEX);
    if (i != 7) Serial.print(":");
  }

  // Check if FF:FF:FF:FF:FF:FF:FF:FF
  // If your button is really programmed with FF:FF:FF:FF:FF:FF:FF:FF, then remove this check
  if (data[0] & data[1] & data[2] & data[3] & data[4] & data[5] & data[6] & data[7] == 0xFF)
  {
    Serial.println("...nothing found!"); 
    return;
  }


  // Check if read key is equal to the one to be programmed
  for (i = 0; i < 8; i++)
    if (data[i] != key_to_write[i])
      break;
    else
      if (i == 7)
      {
        Serial.println("...already programmed!");
        return;
      }

  Serial.println();
  Serial.print("Programming new key...");
  
  for (uint8_t i = 0; i < 8; i++)
  {
    ds.reset();
    data[0] = 0x3C; // "WRITE" command
    data[1] = i; // programming i-th byte
    data[2] = 0;
    data[3] = key_to_write[i];
    ds.write_bytes(data, 4);
    Serial.print(".");
  
    uint8_t crc = ds.read();
    send_programming_impulse();
    if (OneWire::crc8(data, 4) != crc) {
        Serial.print("error!rn");
                Serial.print(OneWire::crc8(data, 4));

        return;
    }
    else
      Serial.print(".");
    
    
  }
  
  Serial.println("done!");
}

void send_programming_impulse()
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH); 
  delay(60);
  digitalWrite(pin, LOW); 
  delay(5);
  digitalWrite(pin, HIGH); 
  delay(50); 
}

Содержание

  1. Arduino.ru
  2. Регистрация новых пользователей и создание новых тем теперь только на новом форуме https://forum.arduino.ru
  3. forum.arduino.ru
  4. Помогите подружить iButton и Arduino.
  5. Вставка программного кода в тему/комментарий
  6. Делаем универсальный ключ для домофона
  7. Немного теории.
  8. Практика.
  9. Морально-этические вопросы.
  10. Python Key Error: How Can You Fix it Fast?
  11. What does key error mean?
  12. How do I fix key errors in Python?
  13. First option
  14. Second option
  15. How do you handle key errors?
  16. Avoiding the KeyError with a For Loop
  17. The Generic Approach For Exceptions
  18. Conclusion

Arduino.ru

Регистрация новых пользователей и создание новых тем теперь только на новом форуме https://forum.arduino.ru

forum.arduino.ru

Помогите подружить iButton и Arduino.

Всем привет. Помогите новичку. Хочу сделать дубликат соего ключа iButton. Купил Arduino и несколько заготовок, пробовал как тут:

Считал я ключ нормально, а при попытке записать ничего не происходит. Резисторы менял разные. Вот скетч:

OneWire ds(pin); // pin 10 is 1-Wire interface pin now

delay(1000); // 1 sec

ds.write(0x33); // «READ» command

if (i != 7) Serial.print(«:»);

// Check if FF:FF:FF:FF:FF:FF:FF:FF

// If your button is really programmed with FF:FF:FF:FF:FF:FF:FF:FF, then remove this check

if (data[0] & data[1] & data[2] & data[3] & data[4] & data[5] & data[6] & data[7] == 0xFF)

Serial.println(«. nothing found!»);

// return; // remove when ready to programm

// Check if read key is equal to the one to be programmed

if (data[i] != key_to_write[i])

Serial.println(«. already programmed!»);

Serial.print(«Programming new key. «);

for (uint8_t i = 0; i

data[0] = 0x3C; // «WRITE» command

data[1] = i; // programming i-th byte

uint8_t crc = ds.read();

if (OneWire::crc8(data, 4) != crc) <

Вставка программного кода в тему/комментарий

а что за ключ для записи ты использовал?

а что за ключ для записи ты использовал?

Уважаемые формучане. Нужна помощь. Исполнительных устройств по реализации с iButton много. Но я не нашел как реализовать чтения электронного ключа сразу двумя ардуинами. Мне нужно чтобы приложив ibutton сработали сразу две андруино. так как они расположенны в разных местах и далеки друг от друга, то самое лучшее решение для меня это параллельное чтитывание.

Пример: Приложив ключ одно ардуино включает электроэнергию в одном месте, другой ардуино в другом.

Не могу понять как реализовать синхронизацию всего этого.

Заранее плагодарю за помощь.

В протоколе 1-Wire последовательная передача осуществляется в полудуплексном режиме (т. е. либо прием, либо передача), внутри дискретно определенных временных интервалов, называемых тайм-слотами.

При разной длине проводов у тебя временные интервалы будут отличаться, внося искажения.

а) использовать три Arduino, одна считывает iButton, и передает ID (либо хранит в себе разешенные ключи и сразу выдает «разрешено»/»запрещено) остальным. Связь по RS-485 (помехоустойчивость) или напрямую RX-TX (если не далее 3 м). Полноценную Arduino можно не брать, достаточно крошки Digispark (размеры 22×20 мм) или ProMini.

б) использовать только две существующие Arduino, при этом одна из них возьмет на себя функции общения с iButton и передачи ID в другую Arduino. По линии связи аналогично п. а)

Спасибо за ответ. Дело в том чтобы осуществить вашу идею выше. понадобиться опять монтаж линии от процессора к процессору. Что очень не хочется делать в помещении где законченный ремонт.

А как вам такая идея. Предположим я расположу например ардуино мастер на расстоянии 10 метров от таблетки. А так сказать пвссивный ардуино (считыватель ключа) непосрественной близости от колодки Ibutton и при записи кода ключа она передаст его (или команду на включение утройствами) по эфиру на частоте 315 мгЦ на третью исполняющую ардуино? Как бы с помехами с вами согласен. Но мне не понятен вопрос синхронизации. Вот например. Обычный домофон понятно как работает и алгоритм считывания кода с таблетки и этих программ много в инете. Но второй ардуино имеет свою тактовую внутреннюю частоту и уж она точно не совпадает с домофоном. Так какая есть возможность синхронизации? По RX-TX все понятно. Но в жизни может возникнуть такая ситуация и в других решениях когда один ардуино выступает в роли ведушего, а второй в роли ведомой флешки. Так каким способом они за синхронизируются? Я полагаю (а вы поправьте если не прав) что ардуино-2 можно запрограмировать в роли таблетки, только с одним условием после сброса и команды на чтение она переходит в режим чтения и параллельно записывает код. Может какое быть? Я слаб в програмировании и контроллерах, у меня область по электроники другая. Я занимаюсь технологиями Тесла, а там контроллеры не выживают. Спасибо вам что уделяете мне внимание.

Источник

Делаем универсальный ключ для домофона

Заголовок получился слишком громким — и ключ не такой и универсальный, и домофон поддастся не любой. Ну да ладно.
Речь пойдет о домофонах, работающих с 1-wire таблетками DS1990, вот такими:

В интернете можно найти множество материалов о том, как читать с них информацию. Но эти таблетки бывают не только read-only. Человеку свойственно терять ключи, и сегодня ларёк с услугами по клонированию DS1990 можно найти в любом подземном переходе. Для записи они используют болванки, совместимые с оригинальными ключами, но имеющие дополнительные команды. Сейчас мы научимся их программировать.

Зачем это нужно? Если отбросить заведомо нехорошие варианты, то самое простое — это перепрограммировать скопившиеся и ставшие ненужными клонированные таблетки от старого домофона, замененного на новый, от подъезда арендованной квартиры, где больше не живете, от работы, где больше не работаете, и т.п.

Сразу оговорюсь, что в описании я опущу некоторые моменты, очевидные для большинства из тех, кто «в теме», но, возможно, не позволящие простому забредшему сюда из поисковика человеку повторить процедуру. Это сделано нарочно. Я хоть и за открытость информации, и считаю, что сведения обо всех уязвимостях должна доводиться до общественности как можно быстрее, но всё же не хочу, чтобы любой желающий мог беспроблемно заходить ко мне в подъезд.

Немного теории.

Как известно, DS1990 характеризуется, в общем случае, одним параметром — собственным идентификационным номером. Он состоит из 8 байт и нанесен на поверхность таблетки. И он же выдаётся в ответ на запрос по 1-wire. На самом деле один из этих байт — это идентификатор типа устройства, ещё один — контрольная сумма, но для нас это всё не принципиально. В памяти домофона прописаны все известные ему ключи, изменять это множество может только компания, домофоном управляющая. Но кроме ключей, явно записанных в память, домофон иногда реагирует на так называемые мастер-ключи, единые для домофонов этого производителя, этой серии, этого установщика. Коды мастер-ключей стараются держать в секрете, но иногда они утекают. За пять минут гугления можно найти порядка 20 мастер-ключей от различных домофонов. У меня стоит «Визит», поэтому выбор пал на ключ 01:BE:40:11:5A:36:00:E1.

Болванки, на которые клонируются ключи, бывают разных типов. У нас в городе самые распространенные — это TM2004. По описанию они поддерживают финализацию, после которой теряют возможность перезаписи и функционируют как самые обычные DS1990. Но по каким-то причинам умельцы, делающие копии, финализацию выполняют не всегда. Возможно потому, что основная масса программаторов на рынке куплена давно и не имеет такой функции, возможно потому, что для финализации требуется повышенное (9В) напряжение. Не знаю. Но факт остаётся фактом, из 4-х ключей, на которых я экспериментировал, финализирован был только один. Остальные легко позволяли менять свой код на какой душе угодно.

Практика.

Собирать программатор будем на Arduino Uno, которая для подобных целей макетирования и сборки одноразовых поделок подходит идеально. Схема простейшая, 1-Wire на то и 1-Wire.

Время сборки устройства на бредборде не превышает пяти минут

Код скетча. Сам алгоритм записи взят тут — domofon-master2009.narod.ru/publ/rabota_s_kljuchom_tm_2004/1-1-0-5
Там, правда, написано, что можно записывать все 8 байт подряд, но у меня так не заработало. Поэтому каждый байт пишется отдельно, через свою команду 0x3C.

После запуска программа раз в секунду опрашивает 1-Wire интерфейс и выдаёт на последовательнй порт считанный с него код. Если это FF:FF:FF:FF:FF:FF:FF:FF, то считаем, что ничего не подключено. В общем случае это, конечно, неверно, так как некоторые болванки, например, TM2004, позволяют записать 8 0xFF в идентификатор ключа, поэтому если ваша таблетка прошита таким кодом, то проверку нужно убрать.

Порядок работы: запускаем, подключаем ключ, чей код хотим узнать, и полученное значение хардкодим в массив key_to_write. Убираем помеченный коментарием return. Снова запускаем и подключаем болванку, она должна прошиться новым ключом. Естественно, что для записи уже известного кода (скажем, мастер-ключа), первый шаг выполнять не требуется.

Если в процессе записи первого байта произошла ошибка, значит ваш ключ не перезаписываемый. Если же ошибка не на первом, а на каком-то из последующих байт, то проверьте контакт между таблеткой и ардуиной.

Успешный лог записи выглядит как-то так:

Спускаемся на улицу, пытаемся открыть соседний подъезд. Работает!

Морально-этические вопросы.

А стоило ли такое выкладывать? Вдруг в мой подъезд сможет зайти бомж и станет там жить?

Ну, во-первых, давайте смотреть правде в глаза — мастер-ключ вам запрограммируют в любом переходе за очень небольшие деньги. Да и в интернете предложений масса. В этом плане полтора хаброжителя, повторивших мой опыт — это капля в море.
Во-вторых, я всё-таки намеренно упустил несколько довольно принципиальных вопросов, которые помешают новичку запустить устройство. Ну а продвинутый человек вряд ли придёт в ваш подъезд, чтобы там спать или творить непотребства.

Поэтому и публикую без малейших сомнений. Пользуйтесь!

Источник

Python Key Error: How Can You Fix it Fast?

The Key Error exception in Python is an exception that most programmers encounter especially when they are getting started with Python dictionaries.

In this article you will learn:

  • What does key error mean in Python
  • How to fix key errors in Python
  • How to handle key errors

Table of Contents

What does key error mean?

A Key Error is a way for Python to tell you that you are trying to access a key that doesn’t exist in a dictionary.

Here’s an example, I create a file called keyerror.py…

I define a dictionary that contains countries and their capitals.

First I print the capital of Italy….

…then I print the capital of France.

And here’s what I get when I run it:

As you can see the value related to the first key of the dictionary (Italy) is printed as we want.

But something happens with the second print statement.

A KeyError appears in the output, and that’s because…

Python raises a KeyError when you attempt to access a key that doesn’t exist in a dictionary.

In this case the key ‘France’ doesn’t exist in the countries dictionary.

Notice also how Python can tell at which line of the code the exception has occurred. This is very useful to find the cause of the error quickly when you have hundreds or thousands of lines of code.

How do I fix key errors in Python?

There are two very basic fixes for the key error if your program is simple:

  1. Avoid referencing the key that doesn’t exist in the dictionary: this can make sense if, for example, the value of the key has been misspelled. It doesn’t apply to this specific case.
  2. Add the missing key to the dictionary: in this case we would add ‘France’ as a key to the dictionary as part of its initial definition.

But those are not robust approaches and don’t prevent a similar error from occurring again in the future.

Let’s look instead at other two options…

First option

Tell Python not to return a KeyError if we try to access a key that doesn’t exist in the dictionary, but to return a default value instead.

Let’s say we want to return the default value ‘Unknown’ for any keys not present in the dictionary…

Here is how we can do it using the dictionary get() method:

And the output becomes:

So, at least in this way we have more control over the way our program runs.

Second option

Verify if a key exists in a dictionary using the in operator that returns a boolean (True or False) based on the existence of that key in the dictionary.

In the example below I use the in operator together with an if else Python statement to verify if a key exists before accessing its value:

When I run it I see…

This is also a good option!

How do you handle key errors?

In the previous section I have introduced the dictionary get() method as a way to return a default value if a key doesn’t exist in our dictionary.

But, what happens if we don’t pass the default value as second argument to the get() method?

Let’s give it a try, being familiar with built-in methods makes a big difference when you write your code:

Do you know what the output is?

Interestingly this time Python doesn’t raise a KeyError exception…

…the get() method simply returns None if the key doesn’t exist in the dictionary.

This means that we can implement conditional logic in our code based on the value returned by the get() method. Here’s an example:

A nice way to avoid that ugly exception 🙂

Avoiding the KeyError with a For Loop

Often a way to handle errors is by using programming constructs that prevent those errors from occurring.

I have mentioned before that a KeyError occurs when you try to access a key that doesn’t exist in a dictionary.

So, one way to prevent a KeyError is by making sure you only access keys that exist in the dictionary.

You could use a for loop that goes through all the keys of the dictionary…

This would ensure that only keys that are present in the dictionary are used in our code.

Let’s have a look at one example:

And the output is…

A for loop can be used to go through all the keys in a dictionary and to make sure you don’t access keys that are not part of the dictionary. This prevents the Python KeyError exception from occurring.

The Generic Approach For Exceptions

Finally, a generic approach you can use with any exceptions is the try except block.

This would prevent Python for raising the KeyError exception and it would allow you to handle the exception in the except block.

This is how you can do it in our example:

As you can see, in this case, the except block is written specifically to handle the KeyError exception.

In this case we could have also used a generic exception (removing KeyError)…

So, do we really need to specify the exception type?

It can be very handy if the try code block could raise multiple types of exceptions and we want to handle each type differently.

Conclusion

Now you have a pretty good idea on how to handle the KeyError exception in Python.

Few options are available to you, choose the one you prefer…

Are you gonna use the get() method or the in operator?

Do you prefer the try except approach?

Let me know in the comments below 🙂

Are you getting started with Python?

I have created a checklist for you to quickly learn the basics of Python. You can download it here for free.

Источник

Заголовок получился слишком громким — и ключ не такой и универсальный, и домофон поддастся не любой. Ну да ладно.
Речь пойдет о домофонах, работающих с 1-wire таблетками DS1990, вот такими:

В интернете можно найти множество материалов о том, как читать с них информацию. Но эти таблетки бывают не только read-only. Человеку свойственно терять ключи, и сегодня ларёк с услугами по клонированию DS1990 можно найти в любом подземном переходе. Для записи они используют болванки, совместимые с оригинальными ключами, но имеющие дополнительные команды. Сейчас мы научимся их программировать.

Зачем это нужно? Если отбросить заведомо нехорошие варианты, то самое простое — это перепрограммировать скопившиеся и ставшие ненужными клонированные таблетки от старого домофона, замененного на новый, от подъезда арендованной квартиры, где больше не живете, от работы, где больше не работаете, и т.п.

Сразу оговорюсь, что в описании я опущу некоторые моменты, очевидные для большинства из тех, кто «в теме», но, возможно, не позволящие простому забредшему сюда из поисковика человеку повторить процедуру. Это сделано нарочно. Я хоть и за открытость информации, и считаю, что сведения обо всех уязвимостях должна доводиться до общественности как можно быстрее, но всё же не хочу, чтобы любой желающий мог беспроблемно заходить ко мне в подъезд.

Немного теории.

Как известно, DS1990 характеризуется, в общем случае, одним параметром — собственным идентификационным номером. Он состоит из 8 байт и нанесен на поверхность таблетки. И он же выдаётся в ответ на запрос по 1-wire. На самом деле один из этих байт — это идентификатор типа устройства, ещё один — контрольная сумма, но для нас это всё не принципиально. В памяти домофона прописаны все известные ему ключи, изменять это множество может только компания, домофоном управляющая. Но кроме ключей, явно записанных в память, домофон иногда реагирует на так называемые мастер-ключи, единые для домофонов этого производителя, этой серии, этого установщика. Коды мастер-ключей стараются держать в секрете, но иногда они утекают. За пять минут гугления можно найти порядка 20 мастер-ключей от различных домофонов. У меня стоит «Визит», поэтому выбор пал на ключ 01:BE:40:11:5A:36:00:E1.

Болванки, на которые клонируются ключи, бывают разных типов. У нас в городе самые распространенные — это TM2004. По описанию они поддерживают финализацию, после которой теряют возможность перезаписи и функционируют как самые обычные DS1990. Но по каким-то причинам умельцы, делающие копии, финализацию выполняют не всегда. Возможно потому, что основная масса программаторов на рынке куплена давно и не имеет такой функции, возможно потому, что для финализации требуется повышенное (9В) напряжение. Не знаю. Но факт остаётся фактом, из 4-х ключей, на которых я экспериментировал, финализирован был только один. Остальные легко позволяли менять свой код на какой душе угодно.

Практика.

Собирать программатор будем на Arduino Uno, которая для подобных целей макетирования и сборки одноразовых поделок подходит идеально. Схема простейшая, 1-Wire на то и 1-Wire.

Время сборки устройства на бредборде не превышает пяти минут

Код скетча. Сам алгоритм записи взят тут — domofon-master2009.narod.ru/publ/rabota_s_kljuchom_tm_2004/1-1-0-5
Там, правда, написано, что можно записывать все 8 байт подряд, но у меня так не заработало. Поэтому каждый байт пишется отдельно, через свою команду 0x3C.

#include <OneWire.h>

#define pin 10

byte key_to_write[] = { 0x01, 0xBE, 0x40, 0x11, 0x5A, 0x36, 0x00, 0xE1 };

OneWire  ds(pin);  // pin 10 is 1-Wire interface pin now

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte data[8];

  delay(1000); // 1 sec
  
  ds.reset();
  delay(50);
  ds.write(0x33); // "READ" command
  
  ds.read_bytes(data, 8);

  Serial.print("KEY ");
  for( i = 0; i < 8; i++) {
    Serial.print(data[i], HEX);
    if (i != 7) Serial.print(":");
  }

  // Check if FF:FF:FF:FF:FF:FF:FF:FF
  // If your button is really programmed with FF:FF:FF:FF:FF:FF:FF:FF, then remove this check
  if (data[0] & data[1] & data[2] & data[3] & data[4] & data[5] & data[6] & data[7] == 0xFF)
  {
    Serial.println("...nothing found!"); 
    return;
  }

  return; // remove when ready to programm

  // Check if read key is equal to the one to be programmed
  for (i = 0; i < 8; i++)
    if (data[i] != key_to_write[i])
      break;
    else
      if (i == 7)
      {
        Serial.println("...already programmed!");
        return;
      }

  Serial.println();
  Serial.print("Programming new key...");
  
  for (uint8_t i = 0; i < 8; i++)
  {
    ds.reset();
    data[0] = 0x3C; // "WRITE" command
    data[1] = i; // programming i-th byte
    data[2] = 0;
    data[3] = key_to_write[i];
    ds.write_bytes(data, 4);
    Serial.print(".");
  
    uint8_t crc = ds.read();
    
    if (OneWire::crc8(data, 4) != crc) {
        Serial.print("error!rn");
        return;
    }
    else
      Serial.print(".");
    
    send_programming_impulse();
  }
  
  Serial.println("done!");
}

void send_programming_impulse()
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH); 
  delay(60);
  digitalWrite(pin, LOW); 
  delay(5);
  digitalWrite(pin, HIGH); 
  delay(50); 
}

После запуска программа раз в секунду опрашивает 1-Wire интерфейс и выдаёт на последовательнй порт считанный с него код. Если это FF:FF:FF:FF:FF:FF:FF:FF, то считаем, что ничего не подключено. В общем случае это, конечно, неверно, так как некоторые болванки, например, TM2004, позволяют записать 8 0xFF в идентификатор ключа, поэтому если ваша таблетка прошита таким кодом, то проверку нужно убрать.

Порядок работы: запускаем, подключаем ключ, чей код хотим узнать, и полученное значение хардкодим в массив key_to_write. Убираем помеченный коментарием return. Снова запускаем и подключаем болванку, она должна прошиться новым ключом. Естественно, что для записи уже известного кода (скажем, мастер-ключа), первый шаг выполнять не требуется.

Если в процессе записи первого байта произошла ошибка, значит ваш ключ не перезаписываемый. Если же ошибка не на первом, а на каком-то из последующих байт, то проверьте контакт между таблеткой и ардуиной.

Успешный лог записи выглядит как-то так:

KEY FF:FF:FF:FF:FF:FF:FF:FF...nothing found!
KEY FF:FF:FF:FF:FF:FF:FF:FF...nothing found!
KEY FF:FF:FF:FF:FF:FF:FF:FF...nothing found!
KEY 1:98:2C:CD:C:0:0:EB
Programming new key...................done!
KEY 1:BE:40:11:5A:36:0:E1...already programmed!

Спускаемся на улицу, пытаемся открыть соседний подъезд. Работает!

Морально-этические вопросы.

А стоило ли такое выкладывать? Вдруг в мой подъезд сможет зайти бомж и станет там жить?

Ну, во-первых, давайте смотреть правде в глаза — мастер-ключ вам запрограммируют в любом переходе за очень небольшие деньги. Да и в интернете предложений масса. В этом плане полтора хаброжителя, повторивших мой опыт — это капля в море.
Во-вторых, я всё-таки намеренно упустил несколько довольно принципиальных вопросов, которые помешают новичку запустить устройство. Ну а продвинутый человек вряд ли придёт в ваш подъезд, чтобы там спать или творить непотребства.

Поэтому и публикую без малейших сомнений. Пользуйтесь!

dont slow down

Posts: 9
Joined: Wed Nov 15, 2017 9:50 pm
Vehicle: 2013 Ford Explorer XLT

Error programming new key to 2013 Explorer

I added remote start to my 2013 Explorer and bought a new key with the extra button. I have the integrated key head and it is an aftermarket key. I tried to program the key to the car and it does work, it starts the car manually, locks and unlocks, and remote start works fine. The programmed key counter now shows 3 keys programmed however when I put the key in and start the car I get a «Could not program integrated key» message on the IPC, which goes away. I was wondering if there was any way to get rid of this error by programming through the PATS option in Forscan, or any other insight possibly? Thank you.

FORScan

Site Admin
Posts: 2840
Joined: Fri Jun 13, 2014 2:21 am

Re: Error programming new key to 2013 Explorer

Post

by FORScan » Fri Nov 24, 2017 12:14 am

DTC B1218: 00 (Transmitter Identification Code: No Sub Type Information) — sets when the BCMdetects an invalid Transmitter Identification Code (TIC) from an IKIntegrated Keyhead Transmitter (IKT)

Most likely, incorrect (non-OEM defective or incompatible) key is used.

Ford service manual says:

NOTE: Make sure the IKTs are those provided with the OEM system and not from an aftermarket system, or a dealer-installed system that may have been installed on the vehicle.
….
Check that the correct IKTs are used with the vehicle. Compare the IKTs with the one shown in Handles, Locks, Latches and Entry Systems in the Description and Operation portion of this section.

The system cannot be tested without the correct IKTs . INFORM the customer that the correct IKTs must be present to proceed with diagnosis of the system.

If you need the full pin point test, please contact our support (by email or just PM here).

Исключения Python KeyError и как их обработать

Исключение PythonKeyError — распространенное исключение, с которым сталкиваются новички. Знание, почемуKeyError может быть повышено, и некоторые решения, позволяющие предотвратить остановку вашей программы, — важные шаги к совершенствованию как программиста Python.

К концу этого руководства вы будете знать:

  • Что обычно означает PythonKeyError

  • Где еще вы могли бы увидетьKeyError в стандартной библиотеке

  • Как обращаться сKeyError, когда вы его видите

Что обычно означаетKeyError в Python

PythonKeyErrorexception — это то, что возникает, когда вы пытаетесь получить доступ к ключу, которого нет вdictionary (dict).

official documentation в Python говорит, чтоKeyError вызывается при обращении к ключу сопоставления и не обнаруживается в сопоставлении. Отображение — это структура данных, которая отображает один набор значений в другой. Наиболее распространенным отображением в Python является словарь.

PythonKeyError является типом исключенияLookupError и означает, что возникла проблема с получением ключа, который вы искали. Когда вы видитеKeyError, семантическое значение состоит в том, что искомый ключ не может быть найден.

В приведенном ниже примере вы можете увидеть словарь (ages) с возрастом трех человек. Когда вы пытаетесь получить доступ к ключу, которого нет в словаре, возникаетKeyError:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'Michael'

Здесь попытка доступа к ключу'Michael' в словареages приводит к подъемуKeyError. В нижней части трассировки вы получите соответствующую информацию:

  • Тот факт, что aKeyError был повышен

  • Ключ, который не удалось найти,'Michael'

Строка от последней к последней говорит вам, какая строка вызвала исключение. Эта информация более полезна, когда вы выполняете код Python из файла.

Note: Когда в Python возникает исключение, это делается с помощьюtraceback. Трассировка предоставляет вам всю необходимую информацию, чтобы определить, почему возникло исключение и что его вызвало.

Умение читать трассировку Python и понимание того, что он говорит вам, крайне важно для улучшения как программиста на Python.

В приведенной ниже программе вы можете снова увидеть словарьages. На этот раз вам будет предложено указать имя человека, для которого необходимо узнать возраст:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 print(f'{person} is {ages[person]} years old.')

Этот код примет имя, которое вы указали в приглашении, и попытается определить возраст этого человека. Все, что вы вводите в командной строке, будет использоваться как ключ к словарюages в строке 4.

Повторяя неудачный пример выше, мы получаем еще одну трассировку, на этот раз с информацией о строке в файле, из которой возникаетKeyError:

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in 
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

Программа не работает, когда вы даете ключ, которого нет в словаре. Здесь последние несколько строк трассировки указывают на проблему. File "ages.py", line 4, in <module> сообщает вам, в какой строке какого файла возникло исключениеKeyError. Тогда вам показывают эту линию. Наконец, исключениеKeyError предоставляет недостающий ключ.

Итак, вы можете видеть, что последняя строка трассировкиKeyError сама по себе не дает вам достаточно информации, но строки перед ней могут значительно приблизить вас к пониманию того, что пошло не так.

Note: Как и в примере выше, большинство других примеров в этом руководстве используютf-strings, которые были введены в Python 3.6.

Где еще вы могли бы увидеть PythonKeyError в стандартной библиотеке

В подавляющем большинстве случаев вызывается PythonKeyError, потому что ключ не найден в словаре или подклассе словаря (например,os.environ).

В редких случаях вы также можете увидеть его поднятым в других местах стандартной библиотеки Python, например, в модулеzipfile, если элемент не найден в ZIP-архиве. Однако эти места сохраняют то же семантическое значение PythonKeyError, которое не находит запрошенный ключ.

В следующем примере вы можете увидеть использование классаzipfile.ZipFile для извлечения информации о ZIP-архиве с помощью.getinfo():

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "", line 1, in 
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

Это не похоже на поиск по словарю. Вместо этого это вызовzipfile.ZipFile.getinfo() вызывает исключение.

Трассировка также выглядит немного иначе, поскольку предоставляется немного больше информации, чем просто отсутствующий ключ:KeyError: "There is no item named 'something' in the archive".

И последнее, на что следует обратить внимание, это то, что строки, которая поднялаKeyError, нет в вашем коде. Он находится в кодеzipfile, но предыдущие строки трассировки указывают, какие строки в вашем коде вызвали проблему.

Когда вам нужно поднять PythonKeyError в собственном коде

Бывают случаи, когдаyou to raise является исключением PythonKeyError в вашем собственном коде. Это можно сделать, используя ключевое словоraise и вызывая исключениеKeyError:

Обычно отсутствующим ключом являетсяmessage. Однако, как и в случае с пакетомzipfile, вы можете указать немного больше информации, чтобы помочь следующему разработчику лучше понять, что пошло не так.

Если вы решили поднять PythonKeyError в своем собственном коде, просто убедитесь, что ваш вариант использования соответствует семантическому значению исключения. Следует отметить, что искомый ключ не может быть найден.

Как обращаться с PythonKeyError, когда вы его видите

Когда вы сталкиваетесь сKeyError, есть несколько стандартных способов справиться с этим. В зависимости от вашего варианта использования, некоторые из этих решений могут быть лучше, чем другие. Конечная цель — предотвратить возникновение неожиданных исключенийKeyError.

Обычное решение:.get()

ЕслиKeyError возникает из-за неудачного поиска ключа словаря в вашем собственном коде, вы можете использовать.get() для возврата либо значения, найденного в указанном ключе, либо значения по умолчанию.

Как и в предыдущем примере поиска возраста, в следующем примере показан лучший способ получить возраст из словаря, используя ключ, указанный в приглашении:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5 age = ages.get(person)
 6
 7 if age:
 8     print(f'{person} is {age} years old.')
 9 else:
10     print(f"{person}'s age is unknown.")

Здесь в строке 5 показано, как можно получить значение возраста изages с помощью.get(). Это приведет к тому, что переменнаяage будет иметь значение возраста, найденное в словаре для предоставленного ключа, или значение по умолчанию,None в этом случае.

На этот раз вы не получите исключениеKeyError из-за использования более безопасного метода.get() для получения возраста, а не попытки получить доступ к ключу напрямую:

$ python ages.py
Get age for: Michael
Michael's age is unknown.

В приведенном выше примере выполненияKeyError больше не возникает, если указан неверный ключ. Ключ'Michael' не найден в словаре, но, используя.get(), мы получаем возвращаемыйNone, а не поднятыйKeyError.

Переменнаяage будет иметь либо возраст человека, найденный в словаре, либо значение по умолчанию (по умолчаниюNone). Вы также можете указать другое значение по умолчанию в вызове.get(), передав второй аргумент.

Это строка 5 из приведенного выше примера с другим возрастом по умолчанию, указанным с помощью.get():

age = ages.get(person, 0)

Здесь вместо'Michael', возвращающегоNone, он вернет0, потому что ключ не найден, а возвращаемое значение по умолчанию теперь0.

Редкое решение: проверка на наличие ключей

Есть моменты, когда вам нужно определить наличие ключа в словаре. В этих случаях использование.get() может не дать вам правильную информацию. ПолучениеNone, возвращенного из вызова.get(), может означать, что ключ не был найден или что значение, найденное для ключа в словаре, на самом делеNone.

Со словарем или подобным словарю объектом вы можете использовать операторin, чтобы определить, присутствует ли ключ в отображении. Этот оператор вернет логическое (True илиFalse) значение, указывающее, найден ли ключ в словаре.

В этом примере вы получаете словарьresponse в результате вызова API. Этот ответ может иметь значение ключаerror, определенное в ответе, что указывает на то, что ответ находится в состоянии ошибки:

 1 # parse_api_response.py
 2 ...
 3 # Assuming you got a `response` from calling an API that might
 4 # have an error key in the `response` if something went wrong
 5
 6 if 'error' in response:
 7     ...  # Parse the error state
 8 else:
 9     ...  # Parse the success state

Здесь есть разница в проверке наличия ключаerror вresponse и получении значения по умолчанию из ключа. Это редкий случай, когда вы на самом деле ищете, если ключ находится в словаре, а не то, каково значение этого ключа.

Общее решение:tryexcept

Как и в случае с любым исключением, вы всегда можете использовать блокtryexcept, чтобы изолировать код, который может привести к возникновению исключения, и предоставить решение для резервного копирования.

Вы можете использовать блокtryexcept в том же примере, что и раньше, но на этот раз предоставив сообщение по умолчанию, которое будет напечатано, еслиKeyError будет поднят в нормальном случае:

 1 # ages.py
 2
 3 ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4 person = input('Get age for: ')
 5
 6 try:
 7     print(f'{person} is {ages[person]} years old.')
 8 except KeyError:
 9     print(f"{person}'s age is unknown.")

Здесь вы можете увидеть нормальный случай в блокеtry печати имени и возраста человека. Резервный случай находится в блокеexcept, где, еслиKeyError поднимается в нормальном случае, тогда резервный вариант должен напечатать другое сообщение.

Блочное решениеtryexcept также является отличным решением для других мест, которые могут не поддерживать.get() или операторin. Это также лучшее решение, еслиKeyError поднимается из кода другого человека.

Вот пример, снова использующий пакетzipfile. На этот раз блокtryexcept дает нам способ остановить исключениеKeyError от остановки программы:

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

Поскольку классZipFile не предоставляет.get(), как это делает словарь, вам необходимо использовать решениеtryexcept. В этом примере вам не нужно заранее знать, какие значения допустимы для передачи.getinfo().

Заключение

Теперь вы знаете несколько распространенных мест, где может возникнуть исключениеKeyErrorв Python, и несколько отличных решений, которые можно использовать, чтобы предотвратить остановку вашей программы.

Теперь, когда вы в следующий раз увидите поднятыйKeyError, вы поймете, что это, вероятно, просто неверный поиск ключа словаря. Вы также сможете найти всю информацию, необходимую для определения источника ошибки, взглянув на последние несколько строк трассировки.

Если проблема заключается в поиске ключа словаря в вашем собственном коде, вы можете переключиться с доступа к ключу непосредственно в словаре на использование более безопасного метода.get() с возвращаемым значением по умолчанию. Если проблема не в вашем собственном коде, то использование блокаtryexcept — лучший вариант для управления потоком кода.

Исключения не должны быть страшными. Как только вы поймете, как понимать информацию, предоставленную вам в их трассировках, и основную причину исключения, вы можете использовать эти решения, чтобы сделать ваши программы более предсказуемыми.

The Key Error exception in Python is an exception that most programmers encounter especially when they are getting started with Python dictionaries.

In this article you will learn:

  • What does key error mean in Python
  • How to fix key errors in Python
  • How to handle key errors

What does key error mean?

A Key Error is a way for Python to tell you that you are trying to access a key that doesn’t exist in a dictionary.

Here’s an example, I create a file called keyerror.py…

I define a dictionary that contains countries and their capitals.

First I print the capital of Italy….

…then I print the capital of France.

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

print(countries['Italy'])
print(countries['France'])

And here’s what I get when I run it:

Rome
Traceback (most recent call last):
  File "keyerror.py", line 3, in <module>
    print(countries['France'])
KeyError: 'France'

As you can see the value related to the first key of the dictionary (Italy) is printed as we want.

But something happens with the second print statement.

A KeyError appears in the output, and that’s because…

Python raises a KeyError when you attempt to access a key that doesn’t exist in a dictionary.

In this case the key ‘France’ doesn’t exist in the countries dictionary.

Notice also how Python can tell at which line of the code the exception has occurred. This is very useful to find the cause of the error quickly when you have hundreds or thousands of lines of code.

Core skill: When Python raises an exception a traceback is included. A traceback is used to give you all the details you need to understand the type of exception and to find what has caused it in your code. 

Makes sense?

How do I fix key errors in Python?

There are two very basic fixes for the key error if your program is simple:

  1. Avoid referencing the key that doesn’t exist in the dictionary: this can make sense if, for example, the value of the key has been misspelled. It doesn’t apply to this specific case.
  2. Add the missing key to the dictionary: in this case we would add ‘France’ as a key to the dictionary as part of its initial definition.

But those are not robust approaches and don’t prevent a similar error from occurring again in the future.

Let’s look instead at other two options…

First option

Tell Python not to return a KeyError if we try to access a key that doesn’t exist in the dictionary, but to return a default value instead.

Let’s say we want to return the default value ‘Unknown’ for any keys not present in the dictionary…

Here is how we can do it using the dictionary get() method:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
default = 'Unknown'

print(countries.get('Italy', default))
print(countries.get('France', default))

And the output becomes:

Rome
Unknown

So, at least in this way we have more control over the way our program runs.

Second option

Verify if a key exists in a dictionary using the in operator that returns a boolean (True or False) based on the existence of that key in the dictionary.

In the example below I use the in operator together with an if else Python statement to verify if a key exists before accessing its value:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

if 'France' in countries:
    print("The capital of France is %" % countries['France'])
else:
    print("The capital of France is unknown")

When I run it I see…

The capital of France is unknown

This is also a good option!

How do you handle key errors?

In the previous section I have introduced the dictionary get() method as a way to return a default value if a key doesn’t exist in our dictionary.

But, what happens if we don’t pass the default value as second argument to the get() method?

Let’s give it a try, being familiar with built-in methods makes a big difference when you write your code:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

print(countries.get('Italy'))
print(countries.get('France'))

Do you know what the output is?

Rome
None

Interestingly this time Python doesn’t raise a KeyError exception…

…the get() method simply returns None if the key doesn’t exist in the dictionary.

This means that we can implement conditional logic in our code based on the value returned by the get() method. Here’s an example:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
  
capital = countries.get('France')

if capital:
    print("The capital is %s" % capital)
else:
    print("The capital is unknown")

The output is:

The capital is unknown

A nice way to avoid that ugly exception 🙂

Avoiding the KeyError with a For Loop

Often a way to handle errors is by using programming constructs that prevent those errors from occurring.

I have mentioned before that a KeyError occurs when you try to access a key that doesn’t exist in a dictionary.

So, one way to prevent a KeyError is by making sure you only access keys that exist in the dictionary.

Ok, but how?

You could use a for loop that goes through all the keys of the dictionary…

This would ensure that only keys that are present in the dictionary are used in our code.

Let’s have a look at one example:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

for key in countries:
    print("The capital of %s is %s" % (key, countries[key]))

And the output is…

The capital of Italy is Rome
The capital of Poland is Warsaw
The capital of UK is London

A for loop can be used to go through all the keys in a dictionary and to make sure you don’t access keys that are not part of the dictionary. This prevents the Python KeyError exception from occurring.

The Generic Approach For Exceptions

Finally, a generic approach you can use with any exceptions is the try except block.

This would prevent Python for raising the KeyError exception and it would allow you to handle the exception in the except block.

This is how you can do it in our example:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
  
try:
    print('The capital of France is %s' % countries['France'])
except KeyError:
    print('The capital of France is unknown')

As you can see, in this case, the except block is written specifically to handle the KeyError exception.

In this case we could have also used a generic exception (removing KeyError)…

try:
    print('The capital of France is %s' % countries['France'])
except:
    print('The capital of France is unknown')

So, do we really need to specify the exception type?

It can be very handy if the try code block could raise multiple types of exceptions and we want to handle each type differently.

Conclusion

Now you have a pretty good idea on how to handle the KeyError exception in Python.

Few options are available to you, choose the one you prefer…

Are you gonna use the get() method or the in operator?

Do you prefer the try except approach?

Let me know in the comments below 🙂

The Python Starter Checklist

Are you getting started with Python?

I have created a checklist for you to quickly learn the basics of Python. You can download it here for free.

Related posts:

I’m a Tech Lead, Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python KeyError Exceptions and How to Handle Them

Python’s KeyError exception is a common exception encountered by beginners. Knowing why a KeyError can be raised and some solutions to prevent it from stopping your program are essential steps to improving as a Python programmer.

By the end of this tutorial, you’ll know:

  • What a Python KeyError usually means
  • Where else you might see a KeyError in the standard library
  • How to handle a KeyError when you see it

What a Python KeyError Usually Means

A Python KeyError exception is what is raised when you try to access a key that isn’t in a dictionary (dict).

Python’s official documentation says that the KeyError is raised when a mapping key is accessed and isn’t found in the mapping. A mapping is a data structure that maps one set of values to another. The most common mapping in Python is the dictionary.

The Python KeyError is a type of LookupError exception and denotes that there was an issue retrieving the key you were looking for. When you see a KeyError, the semantic meaning is that the key being looked for could not be found.

In the example below, you can see a dictionary (ages) defined with the ages of three people. When you try to access a key that is not in the dictionary, a KeyError is raised:

>>>

>>> ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
>>> ages['Michael']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Michael'

Here, attempting to access the key 'Michael' in the ages dictionary results in a KeyError being raised. At the bottom of the traceback, you get the relevant information:

  • The fact that a KeyError was raised
  • The key that couldn’t be found, which was 'Michael'

The second-to-last line tells you which line raised the exception. This information is more helpful when you execute Python code from a file.

In the program below, you can see the ages dictionary defined again. This time, you will be prompted to provide the name of the person to retrieve the age for:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5print(f'{person} is {ages[person]} years old.')

This code will take the name that you provide at the prompt and attempt to retrieve the age for that person. Whatever you type in at the prompt will be used as the key to the ages dictionary, on line 4.

Repeating the failed example from above, we get another traceback, this time with information about the line in the file that the KeyError is raised from:

$ python ages.py
Get age for: Michael
Traceback (most recent call last):
File "ages.py", line 4, in <module>
  print(f'{person} is {ages[person]} years old.')
KeyError: 'Michael'

The program fails when you give a key that is not in the dictionary. Here, the traceback’s last few lines point to the problem. File "ages.py", line 4, in <module> tells you which line of which file raised the resulting KeyError exception. Then you are shown that line. Finally, the KeyError exception provides the missing key.

So you can see that the KeyError traceback’s final line doesn’t give you enough information on its own, but the lines before it can get you a lot closer to understanding what went wrong.

Where Else You Might See a Python KeyError in the Standard Library

The large majority of the time, a Python KeyError is raised because a key is not found in a dictionary or a dictionary subclass (such as os.environ).

In rare cases, you may also see it raised in other places in Python’s Standard Library, such as in the zipfile module, if an item is not found in a ZIP archive. However, these places keep the same semantic meaning of the Python KeyError, which is not finding the key requested.

In the following example, you can see using the zipfile.ZipFile class to extract information about a ZIP archive using .getinfo():

>>>

>>> from zipfile import ZipFile
>>> zip_file = ZipFile('the_zip_file.zip')
>>> zip_file.getinfo('something')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/python/installation/zipfile.py", line 1304, in getinfo
  'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'something' in the archive"

This doesn’t really look like a dictionary key lookup. Instead, it is a call to zipfile.ZipFile.getinfo() that raises the exception.

The traceback also looks a little different with a little more information given than just the missing key: KeyError: "There is no item named 'something' in the archive".

The final thing to note here is that the line that raised the KeyError isn’t in your code. It is in the zipfile code, but previous lines of the traceback indicate which lines in your code caused the problem.

When You Need to Raise a Python KeyError in Your Own Code

There may be times when it makes sense for you to raise a Python KeyError exception in your own code. This can be done by using the raise keyword and calling the KeyError exception:

Usually, the message would be the missing key. However, as in the case of the zipfile package, you could opt to give a bit more information to help the next developer better understand what went wrong.

If you decide to raise a Python KeyError in your own code, just make sure that your use case matches the semantic meaning behind the exception. It should denote that the key being looked for could not be found.

How to Handle a Python KeyError When You See It

When you encounter a KeyError, there are a few standard ways to handle it. Depending on your use case, some of these solutions might be better than others. The ultimate goal is to stop unexpected KeyError exceptions from being raised.

The Usual Solution: .get()

If the KeyError is raised from a failed dictionary key lookup in your own code, you can use .get() to return either the value found at the specified key or a default value.

Much like the age retrieval example from before, the following example shows a better way to get the age from the dictionary using the key provided at the prompt:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5age = ages.get(person)
 6
 7if age:
 8    print(f'{person} is {age} years old.')
 9else:
10    print(f"{person}'s age is unknown.")

Here, line 5 shows how you can get the age value from ages using .get(). This will result in the age variable having the age value found in the dictionary for the key provided or a default value, None in this case.

This time, you will not get a KeyError exception raised because of the use of the safer .get() method to get the age rather than attempting to access the key directly:

$ python ages.py
Get age for: Michael
Michael's age is unknown.

In the example execution above, the KeyError is no longer raised when a bad key is provided. The key 'Michael' is not found in the dictionary, but by using .get(), we get a None returned rather than a raised KeyError.

The age variable will either have the person’s age found in the dictionary or the default value (None by default). You can also specify a different default value in the .get() call by passing a second argument.

This is line 5 from the example above with a different default age specified using .get():

age = ages.get(person, 0)

Here, instead of 'Michael' returning None, it would return 0 because the key isn’t found, and the default value to return is now 0.

The Rare Solution: Checking for Keys

There are times when you need to determine the existence of a key in a dictionary. In these cases, using .get() might not give you the correct information. Getting a None returned from a call to .get() could mean that the key wasn’t found or that the value found at the key in the dictionary is actually None.

With a dictionary or dictionary-like object, you can use the in operator to determine whether a key is in the mapping. This operator will return a Boolean (True or False) value indicating whether the key is found in the dictionary.

In this example, you are getting a response dictionary from calling an API. This response might have an error key value defined in the response, which would indicate that the response is in an error state:

 1# parse_api_response.py
 2...
 3# Assuming you got a `response` from calling an API that might
 4# have an error key in the `response` if something went wrong
 5
 6if 'error' in response:
 7    ...  # Parse the error state
 8else:
 9    ...  # Parse the success state

Here, there is a difference in checking to see if the error key exists in the response and getting a default value from the key. This is a rare case where what you are actually looking for is if the key is in the dictionary and not what the value at that key is.

The General Solution: try except

As with any exception, you can always use the try except block to isolate the potential exception-raising code and provide a backup solution.

You can use the try except block in a similar example as before, but this time providing a default message to be printed should a KeyError be raised in the normal case:

 1# ages.py
 2
 3ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
 4person = input('Get age for: ')
 5
 6try:
 7    print(f'{person} is {ages[person]} years old.')
 8except KeyError:
 9    print(f"{person}'s age is unknown.")

Here, you can see the normal case in the try block of printing the person’s name and age. The backup case is in the except block, where if a KeyError is raised in the normal case, then the backup case is to print a different message.

The try except block solution is also a great solution for other places that might not support .get() or the in operator. It is also the best solution if the KeyError is being raised from another person’s code.

Here is an example using the zipfile package again. This time, the try except block gives us a way to stop the KeyError exception from stopping the program:

>>>

>>> from zipfile import ZipFile
>>> zip = ZipFile('the_zip_file.zip')
>>> try:
...     zip.getinfo('something')
... except KeyError:
...     print('Can not find "something"')
...
Can not find "something"

Since the ZipFile class does not provide .get(), like the dictionary does, you need to use the try except solution. In this example, you don’t have to know ahead of time what values are valid to pass to .getinfo().

Conclusion

You now know some common places where Python’s KeyError exception could be raised and some great solutions you could use to prevent them from stopping your program.

Now, the next time you see a KeyError raised, you will know that it is probably just a bad dictionary key lookup. You will also be able to find all the information you need to determine where the error is coming from by looking at the last few lines of the traceback.

If the problem is a dictionary key lookup in your own code, then you can switch from accessing the key directly on the dictionary to using the safer .get() method with a default return value. If the problem isn’t coming from your own code, then using the try except block is your best bet for controlling your code’s flow.

Exceptions don’t have to be scary. Once you know how to understand the information provided to you in their tracebacks and the root cause of the exception, then you can use these solutions to make your programs flow more predictably.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python KeyError Exceptions and How to Handle Them

In this article let us learn

  • what KeyError exceptions are,
  • why they occur,
  • how to prevent them from occurring and
  • if they still occur then what are the crucial information we need to log for future debugging and
  • how to log this information.

In our journey to become a Proficient Python craftsman, we need to learn to design un-crashable code and this article is a step towards that goal!

If this is the first time ever seeing a python program crash, I recommend reading the article in the link below to hone your Exception Handling skills before continuing with this one.

Exceptions in Python: Everything You Need To Know!

There are 3 main ways to handle KeyError Exceptions in Python. The first 2 ways are about preventing them. We can prevent the error

  • by using the get() method
  • by using the setdefault() method

These 2 methods are provided to us by the dict class

The 3rd way is to

  • Catch them from the except and logging the information needed to debug later.

For those of you in a hurry, use the table of content below to jump to your section of interest.

Let us start by learning what KeyError means.

What is KeyError?

A dictionary is a built-in data-structure in Python used to store key-value pairs.
For example, this line of code

superDict = {'a':'aquaman', 'b':'batman'}

will create a dictionary like this

Here, the dictionary superDict is initialized with 2 key-value pairs.

Now say we wish to access the dict with a key which is not already present inside it like this

print(superDict['c']) # Expecting catwoman here!

Then python will raise a KeyError like this.

Traceback (most recent call last):

  File "<ipython-input-2-7080830d124d>", line 1, in <module>
    c = superDict['c'] # Expecting cat-woman here!

KeyError: 'c'

I am guessing you experienced something similar to this before getting here. So make sure if the key-value pair you are trying to access has been initialized properly.

To summarize, When working with dicts in Python, if we are trying to use a Key that does not match any of the keys stored inside the dict object, Python will raise a KeyError

Python provides some cool tricks to make sure our programs don’t crash if such errors occur.

To prevent KeyError Exceptions python provides us with 2 useful methods as part of the dictionary class.

  • get() method and
  • setdefault() method

Both these methods are useful in 2 different scenarios, let us see how to use them and which one to use in what scenario.

Let us first start with the get() method.

Method#1: Preventing KeyError Exceptions using the get() method

Have a look at the code below

superDict = {'a':'aquaman', 'b':'batman'}
x = superDict.get('c', 'catwoman')
print(x)

Here if the superDict does not contain the key ‘c’, the get() method will set the value for the variable x to be ‘catwoman‘ instead of throwing an exception.

Running the code above will result in the output below

catwoman

Now if we have a look at the objects created by this program, you will see that the dictionary superDict will still have only 2 key-value pairs and the variable x will contain the string ‘catwoman’ as shown below.

This can be also seen at the python prompt

>> superDict
{'a': 'aquaman', 'b': 'batman'}

>> x
'catwoman'

When to use the get() method?

If you wish to avoid KeyError Exception and avoid adding any key-value pairs to the dictionary then use the get() method.

Method#2: Preventing KeyError Exceptions using the setdefault() method

Have a look at the code below.

superDict = {'a':'aquaman', 'b':'batman'}
c = superDict.setdefault('c', 'catwoman')
d = superDict.get('d', 'duperman?!')
print(c)
print(d)

In line-2 we have used to setdefault() method to avoid KeyError and in line-3 we have used the get() method to avoid KeyError. Note that both the keys ‘c’ and ‘d’ are not available in our superDict

Let us run this code and see what happens.

catwoman
duperman?!

As you can see the code ran fine without KeyErrors!

Let us have a quick look at our dictionary superDict!

As you can see in the screenshot above, the setdefault() method has added the new key-value pair ‘c’:’catwoman’ to our superDict, and the get() method has not added anything.

When to use setdefault() method?

Use setdefault() method if you want to avoid KeyError Exception and add a key-value pair to your dictionary in the process.

Method#3: Logging important information about KeyError from the except clause

There are situations/cases where you cannot do much about preventing KeyErrors and all you can do is log the information and debug the exception later on. In such situations, we need to log the important information so that we have the clues necessary to debug this issue.

Let us see what information can we get from KeyError exceptions and how to log them.

Let us start by looking at the error message that the interpreter throws at us by manually forcing a KeyError using the raise statement.

raise KeyError

Running the line of code above leaves us with the following error message

Traceback (most recent call last):

  File "<ipython-input-1-0783d6d4a852>", line 1, in <module>
    raise KeyError

KeyError

As you can see, we are given the exact line number (line 1) and the type of exception (KeyError), both of which are crucial information to help us debug the exception later on. But if we let the python interpreter crash our program, we will not be able to log this information, also the user of our program might not enjoy the view of such a technical/scary error message.

If this is your first raise statement and you are curious to learn more about how to use this tool to enhance your python proficiency, I recommend adding the article in the link below to your reading list and read that after you finish reading this one!

Python: Manually throw/raise an Exception using the “raise” statement

Coming back to this article, let us see how to log the necessary information using try-except clauses.

import traceback

try:
  superDict = {'a':'aquaman', 'b':'batman'}
  print(superDict['c'])
except KeyError as err:
  print("Unknown key: ", err)
  traceback.print_exc()

In the code above, we have placed the problematic code in the try clause and we are using an except clause to catch KeyError exceptions. As soon as catching we are assigning the caught exception object to the variable named err and printing out the information contained inside that object using the line print(“Unknown key: “, err)

We have also imported the traceback module in Python which is used in the last line to help us understand which line of code caused the error.

Running the code above, we can see something like

Unknown key:  'c'
Traceback (most recent call last):
  File "/home/balaji/.config/spyder-py3/temp.py", line 5, in <module>
    print(superDict['c'])
KeyError: 'c'

As you can see we have printed out the error message just as we wanted!

If you look closely, there are 3 pieces of information in this error message

  1. The value inside the caught exception object (err), which is the string ‘c’, the key that caused the error!
  2. The traceback showing where in our code this exception was raised from, line-3 in this case and
  3. The exception type, which is KeyError

If you are curious to know how to control the logging of each individual piece so that you can have a tidier error log, I have an entire article dedicated to just that!
You can read that in the link below.

Python Exceptions: Getting and Handling Error Messages as strings.

And with that, I will conclude this article.

I hope you found this article useful on your journey of python mastery!

Feel free to share this article with your friends and colleagues!

Понравилась статья? Поделить с друзьями:
  • Programmer device is unavailable or error minipro
  • Programat p300 ошибка 701
  • Program1 pas 10 ошибка времени выполнения индекс находился вне границ массива
  • Program1 pas 10 ошибка времени выполнения входная строка имела неверный формат
  • Program will be terminated men of war assault squad 2 как исправить windows 10