попробуйте / за исключением Python - PullRequest
0 голосов
/ 03 ноября 2019

Я использую Python 3, и у меня есть этот цикл, который повторяется в этом списке -

self.settings["db"]["host"] = ["db-0", "db-1"]

Моя проблема в том, что он, кажется, отправляет return self.conn первый вариант все время, db-0вместо того, чтобы пытаться использовать db-1

, у меня есть 2 db контейнерных сервера, и когда я останавливаю один из них - например, db-0, он должен попробовать psycopg2.connect с db-1

  def db_conn(self):
        try:
            for server in self.settings["db"]["host"]:
                self.conn = psycopg2.connect(
                host=server,
                user=self.settings["db"]["user"],
                password=self.settings["db"]["password"],
                database=self.settings["db"]["database"],
                connect_timeout=5,
                )
                return self.conn
        except Exception:
            pass

если цикл не удался, я не хочу, чтобы он return self.conn, только если попытка сработала.

Я также попытался:

  def db_conn(self):
        try:
            for server in self.settings["db"]["host"]:
                self.conn = psycopg2.connect(
                host=server,
                user=self.settings["db"]["user"],
                password=self.settings["db"]["password"],
                database=self.settings["db"]["database"],
                connect_timeout=5,
                )
        except Exception:
            pass
       return self.conn

Ответы [ 3 ]

1 голос
/ 03 ноября 2019

Вы зацикливаетесь на try. Сделайте это наоборот, нажмите try вниз в цикле.

Контракт DbC * ​​1006 *, который пытается предложить текущий код, заключается в возвращении действительного соединения. Давайте сделаем это более явным, написав очень простой помощник. Мы изложим его контракт в строке документации.

def first_true(iterable, default=False, pred=None):
    # from https://docs.python.org/3/library/itertools.html
    return next(filter(pred, iterable), default)


def get_conn_or_none(self, server):
    """Returns DB connection to server, or None if that's not possible."""
    try:
        return psycopg2.connect(
            host=server,
            user=self.settings["db"]["user"],
            password=self.settings["db"]["password"],
            database=self.settings["db"]["database"],
            connect_timeout=5,
        )
    except Exception:
        return None

Теперь db_conn это просто:

def db_conn(self):
    return first_true(map(self.get_conn_or_none, self.settings["db"]["host"]))

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

Кстати, очень странно, что вы, очевидно, храните список имен хостов сервера в себе.settings ["db"] ["host"], учитывая, что отдельный пользователь / pw / db хранится в других полях. Попробуйте переименовать этот список в self.servers.

0 голосов
/ 04 ноября 2019

Этот код сработал для меня:

def db_conn(self):
    for server in self.settings["db"]["host"]:
        try:
            self.print_info("TRYING", server)
            self.conn = psycopg2.connect(
                host=server,
                user=self.settings["db"]["user"],
                password=self.settings["db"]["password"],
                database=self.settings["db"]["database"],
            )
        except:
            self.print_info("SERVER DOWN", server)
            continue
    return self.conn

continue продолжит остальную часть кода, если я получу исключение (неудачное соединение), затем он возвращается к циклу for со вторым элементом в списке.

0 голосов
/ 03 ноября 2019

Вы можете попробовать проверить состояние соединения перед его возвратом:

  def db_conn(self):
        try:
            for server in self.settings["db"]["host"]:
                self.conn = psycopg2.connect(
                host=server,
                user=self.settings["db"]["user"],
                password=self.settings["db"]["password"],
                database=self.settings["db"]["database"],
                connect_timeout=5,
                )
                **if self.conn.isOk()**
                    return self.conn
        except Exception:
            pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...