https://github.com/pypyodbc/pypyodbc
pypyodbc for python で as400のデータベースである db2 for i にodbc接続し、 sqlエラーが発生すると、固まる。
固まってしまう根本原因は、db2 for i側にあるのかもしれませんが、 pypyodbcのsrcを見ると、def ctrl_err(ht, h, val_ret, ansi) 内で 無限ループに陥っているようでした。
なので、以下のように「if i > 10: return」を追加することで、 当座をしのぐことにしました。
def ctrl_err(ht, h, val_ret, ansi): """Classify type of ODBC error from (type of handle, handle, return value) , and raise with a list""" func_name = sys._getframe().f_code.co_name if ansi: state = create_buffer(22) Message = create_buffer(1024*4) ODBC_func = ODBC_API.SQLGetDiagRec if py_v3: raw_s = lambda s: bytes(s,'ascii') else: raw_s = str_8b else: state = create_buffer_u(24) Message = create_buffer_u(1024*4) ODBC_func = ODBC_API.SQLGetDiagRecW raw_s = unicode NativeError = ctypes.c_int() Buffer_len = c_short() err_list = [] number_errors = 1 i = 0 #### ココ while 1: ret = ODBC_func(ht, h, number_errors, state, \ ADDR(NativeError), Message, 1024, ADDR(Buffer_len)) i += 1 #### ココ if i > 10: #### ココ return #### ココ if ret == SQL_NO_DATA_FOUND: #No more data, I can raise #print(err_list[0][1]) state = err_list[0][0] err_text = raw_s('[')+state+raw_s('] ')+err_list[0][1] if state[:2] in (raw_s('24'),raw_s('25'),raw_s('42')): raise ProgrammingError(state,err_text) elif state[:2] in (raw_s('22')): raise DataError(state,err_text) elif state[:2] in (raw_s('23')) or state == raw_s('40002'): raise IntegrityError(state,err_text) elif state == raw_s('0A000'): raise NotSupportedError(state,err_text) elif state in (raw_s('HYT00'),raw_s('HYT01'),raw_s('01000')): raise OperationalError(state,err_text) elif state[:2] in (raw_s('IM'),raw_s('HY')): raise Error(state,err_text) else: raise DatabaseError(state,err_text) break elif ret == SQL_INVALID_HANDLE: #The handle passed is an invalid handle raise ProgrammingError('', 'SQL_INVALID_HANDLE') elif ret == SQL_SUCCESS: if ansi: err_list.append((state.value, Message.value, NativeError.value)) else: err_list.append((from_buffer_u(state), from_buffer_u(Message), NativeError.value)) number_errors += 1 elif ret == SQL_ERROR: raise ProgrammingError('', 'SQL_ERROR')