如何在Python psycopg2中捕获特定的Postgres异常

时间:2016-06-16 06:24:38

标签: python postgresql

默认的psycopg2错误消息太宽泛。大部分时间它只是抛出:

  

psycopg2.OperationalError

没有任何其他信息。因此很难猜测,错误的真正原因是什么 - 不正确的用户凭据,或者仅仅是服务器未运行的事实。所以,我需要一些更合适的错误处理,比如pymysql库中的错误代码。

我看过this页面,但它没有帮助。当我做的时候

except Exception as err:
    print(err.pgcode)

它始终打印无。至于errorcodes,它只是未定义的。我试图导入它,但失败了。所以,我需要一些帮助。

2 个答案:

答案 0 :(得分:0)

对于任何想要快速回答的人:

简答

import traceback  # Just to show the full traceback
from psycopg2 import errors

InFailedSqlTransaction = errors.lookup('25P02')

            try:
                feed = self._create_feed(data)
            except InFailedSqlTransaction:
                traceback.print_exc()
                self._cr.rollback()
                pass # Continue / throw ...

长答案

  1. 转到psycopg2 -> erros.py ,您将找到查找功能lookup(code)
  2. 转到 psycopg2\_psycopg\__init__.py 中的 sqlstate_errors,您会找到所有要作为字符串添加到 lookup 函数中的代码。

答案 1 :(得分:0)

这不是问题的答案,而只是我的想法,不适合发表评论。 在这种情况下,我认为在异常对象中设置 pgcode 会有所帮助,但不幸的是,情况并非如此。

我正在实现一个类似 pg_isready 的 Python 脚本来测试 Postgres 服务是否在给定的地址和端口(例如,localhost49136)上运行。地址和端口可能会或可能不会被任何其他程序使用。

pg_isready 在内部调用 internal_ping()。注意Here begins the interesting part of "ping": determine the cause...的评论:

     /*
      * Here begins the interesting part of "ping": determine the cause of the
      * failure in sufficient detail to decide what to return.  We do not want
      * to report that the server is not up just because we didn't have a valid
      * password, for example.  In fact, any sort of authentication request
      * implies the server is up.  (We need this check since the libpq side of
      * things might have pulled the plug on the connection before getting an
      * error as such from the postmaster.)
      */
     if (conn->auth_req_received)
         return PQPING_OK;

所以 pg_isready 还使用了这样一个事实,即连接上的无效身份验证错误意味着连接本身已经成功,因此服务也已启动。因此,我可以按如下方式实现:

        ready = True

        try:
            psycopg2.connect(
                host=address,
                port=port,
                password=password,
                connect_timeout=timeout,
            )
        except psycopg2.OperationalError as ex:
            ready = ("fe_sendauth: no password supplied" in except_msg)

然而,当异常 psycopg2.OperationalError 被捕获时,ex.pgcodeNone。因此,我无法使用错误代码进行比较并查看异常是否与身份验证/授权有关。我必须检查异常是否有特定消息(如@dhke 指出的in the comment),我认为这有点脆弱,因为错误消息可能会在未来版本中更改,但错误代码很多我认为不太可能改变。