ash*_*ari 13 python odbc pyodbc
我做了以下代码,
import pyodbc
try:
pyodbc.connect('DRIVER={%s};SERVER=%s;DATABASE=%s;UID=%s;PWD=%s' % (driver, server, database, uid, password))
except pyodbc.Error, err:
logging.warn(err)
Run Code Online (Sandbox Code Playgroud)
我得到的错误消息格式是
('HY000', "[HY000] [MySQL][ODBC 5.1 Driver]Access denied for user 'root'@'192.168.2.27' (using password: YES) (1045) (SQLDriverConnect)")
Run Code Online (Sandbox Code Playgroud)
我想只收到错误的消息部分即
Access denied for user 'root'@'192.168.2.27'(using password: YES)
Run Code Online (Sandbox Code Playgroud)
我不知道我是否可以特别注意错误,找不到驱动程序,主机关闭等等.
我也尝试捕获错误:
except pyodbc.OperationalError, err:
logging.warn(err)
except pyodbc.DataError, err:
logging.warn(err)
except pyodbc.IntegrityError, err:
logging.warn(err)
except pyodbc.ProgrammingError, err:
logging.warn(err)
except pyodbc.NotSupportedError, err:
logging.warn(err)
except pyodbc.DatabaseError, err:
logging.warn(err)
except pyodbc.Error, err:
logging.warn(err)
Run Code Online (Sandbox Code Playgroud)
但最后一个总是捕获错误.
Fruthermore我看到pyodbc.Error.message总是空的.我怎样才能在错误中得到消息.
谢谢
Sur*_*nti 26
这对我有用.
try:
cnxn = pyodbc.connect(...)
except pyodbc.Error as ex:
sqlstate = ex.args[0]
if sqlstate == '28000':
print("LDAP Connection failed: check password")
Run Code Online (Sandbox Code Playgroud)
有不同的SQLSTATES,您可以使用if-else语句打印出原因.
同样的,
try:
cnxn = pyodbc.connect(...)
except pyodbc.Error as ex:
sqlstate = ex.args[1]
print(sqlstate)
Run Code Online (Sandbox Code Playgroud)
将通过描述为您提供错误的第二部分.比如ex.args[0]给你28000并ex.args[1]给出[28000] LDAP authentication failed for user 'user' (24) (SQLDriverConnect)
然后,您可以在那里使用字符串操作技术来打印出您想要的内容.希望这可以帮助.
自从 op 提出这个问题以来已经很长时间了,但是这里有一段代码将 pyodbc 错误消息解析为可以使用的漂亮的 Python 异常。这也是为了扩展,我没有处理所有可能的 sqlserver 错误代码。
import re
from enum import Enum, IntEnum, unique
class PyODBCError(Exception):
"""
Handle errors for PyODBC. Offers a error message parser
to apply specific logic depending on the error raise
ODBC error identifier: 23000
pyodbc_error_message (str) -- message raised by PyODBC
Example:
[23000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server] \
Cannot insert explicit value for identity column in table \
'building' when IDENTITY_INSERT is set to OFF.
(544) (SQLExecDirectW) \
"""
error_pattern = re.compile(
r"\[(?P<error_id>.*?)\] \[(?P<operator>.*?)\]\[(?P<driver>.*?)\]\[(?P<database_type>.*?)\](?P<error_message>.+?(?= \()) \((?P<sql_server_error_id>\d*?)\) \(SQLExecDirectW\)"
)
sql_error_code_pattern = re.compile(r"\((?P<sql_server_error_code>\d*?)\) \(SQLExecDirectW\)")
column_pattern = re.compile(r"column \'(?P<column_name>.+?)\'")
table_pattern = re.compile(r"table \'(?P<table_name>.+?)\'")
pyodbc_error_code = 'HY000'
def __init__(self, pyodbc_error_message: str) -> None:
self._parse_error_message(pyodbc_error_message)
def __str__(self) -> str:
return self.error_message
def _parse_error_message(self, pyodbc_error_message: str) -> None:
m = re.match(self.error_pattern, pyodbc_error_message)
self.operator = m.group('operator')
self.error_id = m.group('error_id')
self.driver = m.group('driver')
self.database_type = m.group('database_type')
self.error_message = m.group('error_message')
self.sql_server_error_id = m.group('sql_server_error_id')
@classmethod
def get_message(cls, pyodbc_exception: Exception) -> str:
if pyodbc_exception.args[1] == cls.pyodbc_error_code:
return pyodbc_exception.args[0]
else:
return pyodbc_exception.args[1]
@classmethod
def get_pyodbc_code(cls, pyodbc_exception: Exception) -> str:
if pyodbc_exception.args[1] == cls.pyodbc_error_code:
return pyodbc_exception.args[1]
else:
return pyodbc_exception.args[0]
@staticmethod
def get_exception(error_code: int):
return {
515: IdentityInsertNull,
544: IdentityInsertSetToOff,
2627: PrimaryKeyViolation,
8114: FailedTypeConversion,
102: IncorrectSyntax,
32: InvalidNumberParametersSupplied
}.get(error_code, DefaultException)
@classmethod
def get_sql_server_error_code(cls, pyodbc_code: str, message: str) -> int:
"""
Parses error message raised by PyODBC and return SQL Server Error Code
Looks for the following pattern:
(544) (SQLExecDirectW) -> 544
Args:
pyodbc_error_message (str): Error string raised by PyODBC
Returns:
(int) - SQL Server Error Code
"""
if pyodbc_code == cls.pyodbc_error_code:
return 32
else:
m = re.search(cls.sql_error_code_pattern, message)
if m:
return int(m.group('sql_server_error_code'))
else:
raise ValueError(f"Error raised is not from SQL Server: {message}")
@classmethod
def build_pyodbc_exception(cls, pyodbc_exception: Exception):
pyodbc_code = cls.get_pyodbc_code(pyodbc_exception)
error_message = cls.get_message(pyodbc_exception)
error_code = cls.get_sql_server_error_code(pyodbc_code, error_message)
exception = cls.get_exception(error_code)
raise exception(error_message)
class IdentityInsertNull(PyODBCError):
"""
Handle specific PyODBC error related to Null Value Inserted on Identity Column
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
m = re.search(self.table_pattern, self.error_message)
self.table_name = m.group('table_name')
m = re.search(self.column_pattern, self.error_message)
self.column_name = m.group('column_name')
class IdentityInsertSetToOff(PyODBCError):
"""
Handle specific PyODBC error related to Identity Not Set to On/Off
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
m = re.search(self.table_pattern, self.error_message)
self.table_name = m.group('table_name')
class FailedTypeConversion(PyODBCError):
"""
Handle specific PyODBC error related to data type conversion
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
class PrimaryKeyViolation(PyODBCError):
"""
Handle specific PyODBC error related to Primary Key Violation
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
class IncorrectSyntax(PyODBCError):
"""
Handle specific PyODBC error related to incorrect syntax in query
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
class DefaultException(PyODBCError):
"""
Handle default PyODBC errors
"""
def __init__(self, pyodbc_error_message):
super().__init__(pyodbc_error_message)
def __str__(self) -> str:
return f"{self.sql_server_error_id} - {self.error_message}"
class InvalidNumberParametersSupplied(Exception):
def __init__(self, error_message) -> None:
self.message = error_message
def __str__(self) -> str:
return self.message
Run Code Online (Sandbox Code Playgroud)