Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 27, 2017 20:54:20

VadimK
Зарегистрирован: 2013-07-03
Сообщения: 199
Репутация: +  16  -
Профиль   Отправить e-mail  

Django - подключение к внешней базе данных по задаче.

Есть проект на Djnago + UWSGI, который так же используется в качестве задач (аналог celery).
python 3 , в качестве драйвера к базе данных - mysqlclient

Необходимо на одной из страниц подключатся к базе данных на другом сервере и вытаскивать из нее данные.

tasks.py , который осуществляет вызов

 from project.redmine.agregator import Redmine
@task(executor=TaskExecutor.SPOOLER, retry_count=1, retry_timeout=5)
def redmine_data_update():
    r = Redmine()
    r.import_tasks()

agregator.py , собственно как все происходит
 import logging
log = logging.getLogger('tasks')
class Redmine:
    db = None
    def __init__(self):
        self.db = _mysql.connect(host=settings.REDMINE_DB_HOST, db=settings.REDMINE_DB_NAME,
                                 user=settings.REDMINE_DB_USER, passwd=settings.REDMINE_DB_PASS)
        self.db.query("SET NAMES utf8;")
        self.db.query("SET CHARACTER SET utf8;")
        self.db.query("SET character_set_connection=utf8;")
        log.info('MySQL connection to redmine opened.')
    def __del__(self):
        self.db.close()
        log.info('MySQL connection to redmine closed.')
    def import_tasks(self):
        query = "SELECT ... сам запрос"
        try:
            self.db.query(query)
            res = self.db.use_result()
            rs = list(RedmineTasks.objects.filter().values_list('task_id', flat=True))
        except Exception as e:
            log.error('MySQL error: %s' % e)
            return
        row = res.fetch_row()

Проблема в том, что через пару часов перестает работать по причине “MySQL server has gone away”.
Т.е. изначально в логе вижу корректное
 (tasks:24) MySQL connection to redmine opened.
(tasks:28) MySQL connection to redmine closed.
На внешнем сервере соединения закрываются и хвостов нет. А через какое то время уже:
 (tasks:24) MySQL connection to redmine opened.
(tasks:48) MySQL error: (2006, 'MySQL server has gone away')
и на сервере куча не закрытых коннекшенов.

Собственно несколько вопросов:
1. почему при екзепшене и выходе из функции не срабатывает __del__ метод
2. как красиво решить задачу без принудительного вызова метода закрытия коннекшена


Офлайн

#2 Июнь 28, 2017 05:32:24

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Django - подключение к внешней базе данных по задаче.

Сделайте открытие/закрытие соединения в блоке try … finally … вместо __init__/__del__, это вам не c++.
И, кстати, django же умеет соединения к разным базам из коробки, зачем так грубо - настройки подключения в коде.



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#3 Июнь 28, 2017 05:57:07

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

Django - подключение к внешней базе данных по задаче.

Офлайн

#4 Июнь 28, 2017 10:58:22

VadimK
Зарегистрирован: 2013-07-03
Сообщения: 199
Репутация: +  16  -
Профиль   Отправить e-mail  

Django - подключение к внешней базе данных по задаче.

PooH
Сделайте открытие/закрытие соединения в блоке try … finally … вместо __init__/__del__, это вам не c++.
И, кстати, django же умеет соединения к разным базам из коробки, зачем так грубо - настройки подключения в коде.
Там просто несколько разных методов в классе, которые вытягивают разные данные. Хотелось бы в конструкторе открыть соединение, а в деструкторе закрыть.
Но __del__ почему то не всегда вызывается.

А по поводу соединения - просто в данном случае удобнее. Так как нигде более та база не используется и нет смысла ее в проект тащить.

Офлайн

#5 Июнь 28, 2017 12:40:38

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Django - подключение к внешней базе данных по задаче.

VadimK
Там просто несколько разных методов в классе, которые вытягивают разные данные. Хотелось бы в конструкторе открыть соединение, а в деструкторе закрыть.
Ну поместите вызовы этих методов в один try .. finally или сделайте класс менеджером контекста в __enter__ откройте в __exit__ закройте.
VadimK
Но __del__ почему то не всегда вызывается.
Потому что на объект могут быть ссылки. Еще раз говорю - это не c++, __del__ может быть вызван когда счетчик ссылок на объект обнуляется, а если ссылки циклические (один объект на другой, а другой на первый), то когда сборщик мусора придет. А если процесс завершится раньше чем счетчики обнулятся, то может вообще не вызваться. Честно говоря, не скажу как тут соединение к базе будет закрыто, как бы не по таймауту.
VadimK
А по поводу соединения - просто в данном случае удобнее. Так как нигде более та база не используется и нет смысла ее в проект тащить.
Я и вижу насколько удобнее, вместо готового пула пилите велосипед(гарна штука лисопед, попа едет, ноги нет). И настройки вместо конфига расползаются по коду.

PS: насчет настроек не прав, уже после глянул первое сообщение с кодом и увидел что они из конфига



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Отредактировано PooH (Июнь 28, 2017 18:30:38)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version