简体   繁体   中英

python try/except in loop

Im using python 3 and i have this loop, which iterate on this list -

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

My problem is that it seems to send in return self.conn the first option all the time, db-0 instead of trying with db-1

I have 2 db container servers, and when i stop one of them - for example db-0 it should try psycopg2.connect with 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

if loop has not succeeded i dont want it to return self.conn , only if the try worked.

I also tried:

  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

You are looping within a try . Do it the other way around, push the try down within the loop.

The DbC contract the current code is attempting to offer is to return a valid connection. Let's make that more explicit, by writing a very simple helper. We will spell out its contract in a docstring.

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

Now db_conn is simply:

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

That uses the same logic as in your question. You may want to have db_conn additionally check whether all connection attempts failed, and raise fatal error in that case.

BTW, it's very odd that you're apparently storing a list of server hostnames in self.settings["db"]["host"], given that an individual user / pw / db is stored in the other fields. Consider renaming that list to self.servers .

You can try to check the connection status before returning it:

  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

This code worked for me:

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 will continue the rest of the code if i get exception ( failed connection) then it goes back to for loop with the second item in list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM