Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 13, 2017 09:36:24

dake
Зарегистрирован: 2017-04-13
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

вопрос по декораторам

всем привет!
пишу некий мигратор, делаю через класс … хочу чтобы для любой функции работающей с данными вначале выполнялось подключение к базе
пытаюсь сделать через декораторы… походу неправильно

 import cx_Oracle
import psycopg2
from configparser import ConfigParser
class DbMigration2:
    # получение параметров подключений у обеих баз
    # из ini файла
    def __init__(self, settings):
        parser = ConfigParser()
        parser.read(settings)
        _conn_oracle_sett = {}
        _conn_postgres_sett = {}
        if parser.has_section('oracle') and parser.has_section('postgres'):
            params = parser.items('oracle')
            for param in params:
                _conn_oracle_sett[param[0]] = param[1]
            params = parser.items('postgres')
            for param in params:
                _conn_postgres_sett[param[0]] = param[1]
        else:
            raise Exception('Секции отсуствуют')
        self._conn_oracle_sett = _conn_oracle_sett
        self._conn_postgres_sett = _conn_postgres_sett
    def _connect_to_oracle(self):
        """ создание подключения к базе oracle """
        self._dsn = cx_Oracle.makedsn(self._conn_oracle_sett["host"], self._conn_oracle_sett["port"],
                                      self._conn_oracle_sett["sid"])
        self._oracle_conn = cx_Oracle.connect(self._conn_oracle_sett["user"], self._conn_oracle_sett["password"], self._dsn)
    def _connect_to_postgres(self):
        """ создание подключения к базе postgres """
        self._conn_postgres_string = " ".join(["%s=%s" % (k, v) for k, v in self._conn_postgres_sett.items()])
        # print(self._conn_string)
        self._postgres_conn = psycopg2.connect(self._conn_postgres_string)
    def postgres_connector(self, func):
        def wrapper():
            self._connect_to_postgres()
            func()
        return wrapper
    def oracle_connector(self, func):
        def wrapper():
            self._connect_to_oracle()
            func()
        return wrapper
    @postgres_connector
    @oracle_connector
    def export_abonents(self):
        """ Производит заливку лицевых счетов из БИТТл в таблицы хранилища """
        try:
            # получаем лицевые счета абонентов из БИТТл
            or_cur = self._oracle_conn.cursor()
            sql = "select id from db.abonent"
            or_cur.execute(sql)
            # abns = [ abn[0] for abn in or_cur.fetchall()]
            abns = or_cur.fetchall()
            pg_cur = self._postgres_conn.cursor()
            # получаем список таблиц в которые будем заливать лицевые счета абонентов с БИТТл
            sql = "select table_name from storage.data_type dt where dt.base = %s"
            pg_cur.execute(sql, ("ABN", ))
            tables = [ tp[0] for tp in pg_cur.fetchall()]
            #  обнуляем эти таблицы и заливаем туда лицевые счета
            for tbl in tables:
                sql = 'truncate table '+ tbl
                pg_cur.execute(sql)
                sql = "insert into "+ tbl +"(abonent_id) values(%s)"
                pg_cur.executemany(sql, abns)
            pg_cur.commit()
        finally:
            self._oracle_conn.close()
            self._postgres_conn.close()
ошибка вываливается

Traceback (most recent call last):
File “main.py”, line 1, in <module>
import db_migration as dbmigr
File “D:\Projects\telecom\westkazportal\migration\db_migration.py”, line 5, in <
module>
class DbMigration2:
File “D:\Projects\telecom\westkazportal\migration\db_migration.py”, line 51, in
DbMigration2
@oracle_connector
TypeError: oracle_connector() missing 1 required positional argument: ‘func’

подскажите как надо
заранее спасибо!

Отредактировано dake (Апрель 13, 2017 09:37:22)

Офлайн

#2 Апрель 13, 2017 11:32:23

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

вопрос по декораторам

 class Foo(object):
    def decorator(self, func):
        def wrapper():
            func()
        return wrapper
    @decorator
    def foo(self):
        print "OK!"
f = Foo()
f.foo()

 Traceback (most recent call last):
  File "/Users/asmirnov/PycharmProjects/test2/test.py", line 1, in <module>
    class Foo(object):
  File "/Users/asmirnov/PycharmProjects/test2/test.py", line 8, in Foo
    @decorator
TypeError: decorator() takes exactly 2 arguments (1 given)

Ошибка очевидна - методу класса в качестве первого параметра должна быть передана ссылка на объект. Но постольку поскольку вы используете метод как декоратор, в него передается только декорируемая функция. Таким образом, чтобы декораторы заработали, вам надо вынести их из класса



Офлайн

#3 Апрель 13, 2017 11:49:00

ziro
От:
Зарегистрирован: 2009-08-13
Сообщения: 225
Репутация: +  8  -
Профиль   Отправить e-mail  

вопрос по декораторам

Посмотрите например здесь: https://github.com/django/django/blob/master/django/utils/decorators.py

Вам может помочь что-то типа декоратора method_decorator превращает декораторы функций в декораторы методов класса.



Офлайн

#4 Апрель 13, 2017 13:11:20

dake
Зарегистрирован: 2017-04-13
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

вопрос по декораторам

вам надо вынести их из класса
а как мне вынести их из класса, если я там вызываю функцию из этого класса)

Офлайн

#5 Апрель 13, 2017 16:16:07

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

вопрос по декораторам

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



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version