Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » [РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address' [RSS Feed]

#1 Авг. 21, 2015 00:11:28

TitanFighter
Зарегистрирован: 2015-06-23
Сообщения: 99
Репутация: +  0  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

Добрый день.

Целый вечер уже бьюсь над ошибкой. Помогите пожалуйста кто чем может решить ее.
Парсю данные и заливаю их в БД.

### часть кода из 1го метода, который завершается формированием словаря
                basic_dict[self.country][city.text.lstrip()][name] = dict(detailed_url=detailed_url,
                                                                        place_type = self.place_type)
### тут 2ой метод, который завершается расширением первого словаря
                            extended_dict[self.country][city][cinema].update(dict(address = street1,
                                                                            phone_number = phone1,
                                                                            official_website = website1))
        self.showtime(extended_dict)
### тут 3ий метод, который принимает расширенный словарь и начинает уже парсить данные и заливать в БД.
    def showtime(self, extended_dict):
        showtime_dict = extended_dict
        for city in showtime_dict[self.country]:
            for cinema in showtime_dict[self.country][city]:
                url = showtime_dict[self.country][city][cinema]['detailed_url']
                showtimes_tab_url = '/showtimes/#!=&cinema-section=%2Fshowtimes%2F'
                tree = prepare_content(url + showtimes_tab_url)
                for film in tree.xpath('//div[@class="content"]'):
                    film_name = film.xpath('.//a[@class="navi"]/text()')[0]
                    for date in film.xpath('.//li[contains(@class,"showtimes-day sdt")]'):
                        film_date = date.xpath('.//div[@class="date"]/text()')[0]
                        for time in date.xpath('.//ul[@class="showtimes-day-block"]/li'):
                            film_time = time.xpath('string(a/text())')
                            film_buy_ticket_url = time.xpath('string(a/@href)')
                            if len(film_time) == 0:
                                film_time = None
                            is_3d = time.find('span')
                            film_format = ''
                            if film_time is not None:
                                if is_3d is not None:
                                    film_format = '3D'
                                else:
                                    film_format = '2D'
                                # IMPORT
                                from app_places.models import Place
                                from app_shows_and_times.models import Show, Showtime
                                get_showtime_place = Place.objects.get(place_name = cinema, place_street = showtime_dict[self.country][city][cinema]['address'])
                                get_showtime_show = Show.objects.get(show_name = film_name)
                                showtime = Showtime.objects.create(
                                                                showtime_dates = film_date,
                                                                showtime_times = film_time,
                                                                showtime_format = film_format,
                                                                showtime_buy_ticket_url = film_buy_ticket_url,
                                                                showtime_place = get_showtime_place,
                                                                showtime_show = get_showtime_show)

Часть модели (и так уже кода много), где можно увидеть, что 2 поля идут как уникальные.
class Place(models.Model):
    place_name = models.CharField(max_length = 50, db_index = True)
    place_street = models.CharField(max_length = 80)
    place_phone = models.CharField(max_length = 60)
    place_official_site = models.URLField(max_length = 255, blank = True)
    place_country = models.ForeignKey(Country)
    place_city = models.ForeignKey(City)
    place_type = models.ForeignKey(PlaceType)
    class Meta:
        db_table = 'place'
        unique_together = (('place_name', 'place_street'))

Проблема. Запускаю класс, пошел импорт, который заканчивается KeyError: ‘address’, при том что 4700 записей в БД уже создано (базу предварительно очищаю), значит, как я понимаю, до какого-то этапа данное выражение:
get_showtime_place = Place.objects.get(place_name = cinema, place_street = showtime_dict)
работает. Но никак не могу понять, откуда возникает сбой.

Соответственно 3 вопроса:
1) Правильно ли я использую unique? Т.е. в модели задал в мета классе, а в objects.get указываю оба эти поля. Так и нужно?
2) Нужно ли для place_street = models.CharField(max_length = 80) делать db_index = True?
3) По какой причине может идти заливка в БД со ссылкой на ‘address’ в словаре, и в итоге выдавать ошибку?
Как одно из предположений, возможно 4700 записи и должно быть, но я тогда не понимаю, почему процесс заканчивается ошибкой.

Простите за кучу кода.

Едит1:
Думал уже, может где-то в базе Place нету записи street. Проверил - улицы везде указаны.

Отредактировано TitanFighter (Авг. 21, 2015 14:08:39)

Офлайн

#2 Авг. 21, 2015 01:29:58

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

TitanFighter
Всегда указывайте полный traceback ошибки, т.е. полный вывод

В extended_dict в какой то момент нету такого ключа. Если у вас стопориться процесс при 4700 записи, посмотрите что будет происходить при итерации 4701, скорее всего просто одна запись не обрабатывается должным образом.



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#3 Авг. 21, 2015 01:33:11

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

И еще , есть такая штука PEP8, если не слышали - то пролистайте, ознакомьтесь. Я к тому что комментарии у вас какие то странные, да и и импорт принято в начале файла указывать (есть конечно случаи когда можно по другому поступать, но это не тот)



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#4 Авг. 21, 2015 01:47:46

TitanFighter
Зарегистрирован: 2015-06-23
Сообщения: 99
Репутация: +  0  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

Выкладываю трейсбек. Буду знать на следующий раз, что нужно полный. Спасибо.

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/antonio/projects/idemvdvoem.com/idemvdvoem.com/src/shared/parser_to_db.py", line 23, in __init__
    self.basic_cinemas_info()
  File "/home/antonio/projects/idemvdvoem.com/idemvdvoem.com/src/shared/parser_to_db.py", line 176, in basic_cinemas_info
    self.detailed_cinemas_info(basic_dict)
  File "/home/antonio/projects/idemvdvoem.com/idemvdvoem.com/src/shared/parser_to_db.py", line 225, in detailed_cinemas_info
    self.showtime(extended_dict)
  File "/home/antonio/projects/idemvdvoem.com/idemvdvoem.com/src/shared/parser_to_db.py", line 271, in showtime
    get_showtime_place = Place.objects.get(place_name = cinema, place_street = showtime_dict[self.country][city][cinema]['address'])
KeyError: 'address'

Касательно проверить 4701 запись. 4700 записей - это сеансы в кинотеатрах. Сам словарь extended_dict не хранит всю эту тучу записей. Данные, которые собираются на протяжении 2х методов, которые непосредственно хранятся в extended_dict - это инфа о 64х кинотеатрах (адрес, тел) + ссылка на страницу расписания каждого кинотеатра. Это все заливается в базу (всего 64 объекта с максимум 10 столбиками) и только потом в 3ем методе подставляя эту ссылку на расписание, начинается вытягивание даты, времени, формата и тд с сайта и идет запись в БД. Так что, как я понимаю, тут не получиться попробовать получить 4701ый объект.

Про импорт и комментарии: первые 3 - это я описал для поста. Про коммент #IMPORT и про место самого импорта я знаю - это временно пометить себе, чтоб легче было находить глазами (черновой вариант вообщем. В чистовике все чисто ) Но все равно спасибо за внимание, ведь мог и не знать.

Отредактировано TitanFighter (Авг. 21, 2015 01:52:13)

Офлайн

#5 Авг. 21, 2015 03:40:55

TitanFighter
Зарегистрирован: 2015-06-23
Сообщения: 99
Репутация: +  0  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

Только лег в кровать, пришло озарение, как можно найти проблему.
У меня есть модель Showtimes, которая связана через FK с Places.
1 кинотеатр с адресом ул. Лаврухина, 4. ТЦ “РайON” вообще не проимпортировался в Places. Подумал, что может скобки. Проверил - .replace('“', “'”).replace('”', “'”).replace('“', ”'") - не помогло.
Может проблема в кириллице+латинице в названии?
Может как то unique_together влияет? У меня postgreSQL

Может теперь будет кому-то легче подсказать, куда мне ковырять?

Отредактировано TitanFighter (Авг. 21, 2015 04:09:14)

Офлайн

#6 Авг. 21, 2015 05:27:23

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

Да при чем тут unique_together? У вас же не при обращениях к БД ошибка, а в алгоритме, вот тут

showtime_dict[self.country][city][cinema]['address']
KeyError: ‘address’ означает, что в словаре, который вы получили
showtime_dict[self.country][city][cinema]
нет ключа address.
У тут вообще не при чем ни постгресс, ни индексы в нём, ни количество записей в базе, а имеет значение лишь то, что где-то выше вы неправильно создали словарь.



Офлайн

#7 Авг. 21, 2015 12:20:46

i.slepov
Зарегистрирован: 2015-05-28
Сообщения: 53
Репутация: +  5  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

Чтобы не было ошибок “KeyError” используйте метод словаря get.

Вместо:

showtime_dict[self.country][city][cinema]['address']

Нужно:

showtime_dict[self.country][city][cinema].get('address', ' ')

Офлайн

#8 Авг. 21, 2015 14:05:53

TitanFighter
Зарегистрирован: 2015-06-23
Сообщения: 99
Репутация: +  0  -
Профиль   Отправить e-mail  

[РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address'

FishHook
Да при чем тут unique_together? У вас же не при обращениях к БД ошибка, а в алгоритме, вот тут
showtime_dict
KeyError: ‘address’ означает, что в словаре, который вы получили
showtime_dict
нет ключа address.
У тут вообще не при чем ни постгресс, ни индексы в нём, ни количество записей в базе, а имеет значение лишь то, что где-то выше вы неправильно создали словарь.
В 4 ночи уже ничего не хочется, кроме как обнять подушку . Утром прочитав ваши мысли, на свежую голову, я полностью с вами был согласен.
____
i.slepov
Чтобы не было ошибок “KeyError” используйте метод словаря get.
Вместо:
showtime_dict

Нужно:
showtime_dict.get('address', ‘ ’)
Я думал так сделать, но это был бы костыль в том смысле, что данные по нему вообще бы просто пропускались, так как данный кинотеатр даже не заливался в БД (не говоря уже о сеансах, из-за чего и создал этот топик).
____

А проблему таки решил. Оказалось, что при парсинге для одного кинотеатра не оказалось информации об официальном веб-сайте (вот млин для 64 есть, а для 1го нету ). Так как я проверку полей не делал, то в словарь не добавлялись данные cinema_street, cinema_phone, cinema_website для этого одного кинотеатра. Нету данных -> ошибка.

Мой код без проверки наличия данных на сайте:

    for city in extended_dict[country]:
        for cinema in extended_dict[country][city]:
            url = extended_dict[country][city][cinema]['detailed_url']
            tree = prepare(url)
    
            for street in tree.xpath(".//div[@class='address']"):
                cinema_street = street.xpath("text()")[0].strip()
    
                for phone in tree.xpath(".//div[@class='phone']"):
                    cinema_phone = phone.xpath("text()")[0].replace('Телефон:', '').strip()
                    
                    for website in tree.xpath(".//div[@class='website']/a"):
                        cinema_website = website.xpath("@href")[0].strip()
    
                        extended_dict[country][city][cinema].update(dict(address = cinema_street,
                                                                        phone_number = cinema_phone,
                                                                        official_website = cinema_website))

Итог: Нужно всегда делать проверку данных
Всем спасибо.

Отредактировано TitanFighter (Авг. 21, 2015 14:06:46)

Офлайн

  • Начало
  • » Django
  • » [РЕШЕНО] После долгого импортирования в БД (в чистую базу успешно заливаются более 4700 записей), возникает ошибка KeyError: 'address' [RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version