Функция, возвращающая значение из базы данных MySQL в Twisted - PullRequest
0 голосов
/ 17 февраля 2020

У меня есть MySQL база данных, которая содержит несколько таблиц, имеющих структуру, подобную этой:

CREATE TABLE IF NOT EXISTS `table1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key1` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE (`key1`)
);

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

  1. Проверить, присутствует ли указанное значение в столбце key таблицы.
  2. Если оно есть, вернуть соответствующее ему id.
  3. Если это не так, вставить это значение в таблицу и вернуть соответствующее ему id.

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

Как я могу это сделать? Я не могу сделать

import MySQLdb

from twisted.python import log
from twisted.enterprise.adbapi import ConnectionPool
from twisted.internet.defer import inlineCallbacks

class ReconnectingConnectionPool(ConnectionPool):
    def _runInteraction(self, interaction, *args, **kw):
        try:
            return ConnectionPool._runInteraction(
                self, interaction, *args, **kw)
        except MySQLdb.OperationalError as e:   # pylint: disable=no-member
            if e[0] not in (2003, 2006, 2013):
                raise e
            conn = self.connections.get(self.threadID())
            self.disconnect(conn)
            # Try the interaction again
            return ConnectionPool._runInteraction(
                self, interaction, *args, **kw)

dbh = ReconnectingConnectionPool(
    'MySQLdb',
    db='database',
    user='user',
    passwd='password'
)

@inlineCallbacks
def get_id(table, column, entry):
    try:
        r = yield dbh.runQuery("SELECT `id` FROM `{}` WHERE `{}` = '{}'".format(table, column, entry))
        if r:
            id = r[0][0]
        else:
            yield dbh.runQuery("INSERT INTO `{}` (`{}`) VALUES ('{}')".format(table, column, entry))
            r = yield dbh.runQuery('SELECT LAST_INSERT_ID()')
            id = int(r[0][0])
    except Exception as e:
        log.msg(e)
        id = 0
    return id

, потому что функция get_id является генератором, и они не могут возвращать значения напрямую.

Должен ли я использовать defer.returnValue(id) вместо return id? Или я должен использовать dbh.runQuery('query').addCallback(get_result), где get_result - это функция, подобная этой

def get_result(value):
    return value

Или я должен сделать что-то еще?

1 Ответ

0 голосов
/ 19 февраля 2020

сама функция get_id возвращает deferred, поскольку вы используете inlineCallbacks для ее обертывания.

, затем вы вызываете свою функцию с помощью:

get_id().addCallback(your_callback_to_retrive_the_id)

в вашей функции get_id, если вы используете python3, вы можете использовать оператор return или defer.returnValue для возврата результата.

В python2 вы можете использовать только defer.returnValue

from __future__ import print_function

from twisted.internet import reactor
from twisted.internet.defer import Deferred, returnValue, inlineCallbacks



def runQuery(query):
    # suppose this will fetch the result from database
    d = Deferred()

    # simulate the delay waiting for the database to give the results
    # using reactor.callLater
    reactor.callLater(0.3, d.callback, 1); # 1 here is the (result)
    return d


@inlineCallbacks
def get_id(table, column, entry):
    r = yield runQuery("foobar")
    # r is the result from the database
    #if python3
    return r # or returnValue(r)

    # if python2
    # returnValue(r)


# every time you call a function that is wrapped with inlineCallbacks
# the return value of that function is Deferred

d = get_id('messages', 'message', 'Foo')
d.addCallback(lambda r: print("Result: %r" % (r, )))

reactor.run()
...