Python 'utf-16-le' Ошибка при получении столбцов из таблицы базы данных MS Access - PullRequest
0 голосов
/ 06 мая 2020

Я получаю следующую ошибку:

 UnicodeDecodeError: 'utf-16-le' codec can't decode bytes in position 372-373: illegal UTF-16 surrogate

Код появляется только иногда, и я не понимаю почему. Иногда печатаются столбцы, а иногда я получаю сообщение об ошибке. код выполняет цикл по пути к файлу, захватывает базы данных доступа, а затем получает столбцы, которые существуют для таблицы "mytablename". в столбцах нет специальных символов.

 filepathlocation = '//testfilepath'
 access_driver = datasources['MS Access Database']


for filename in os.listdir(filepathlocation):
     if filepathlocation.endswith(".mdb"): 

         fullfilepath = os.path.join(filepathlocation, filename)
         accessConn = pyodbc.connect(driver = access_driver, dbq = fullfilepath)
         accessCur = accessILIConn.cursor()

        for row in accessCur.columns(table='myTableName'):
             accesscolumnnames = accesscolumnnames + row.column_name + ';'

        print(accesscolumnnames)

Я видел в другом посте, где это использовалось

for fld in cursor2.columns(rows.table_name.decode('utf-16-le')):

Я не уверен, как изменить свой код, чтобы следовать этому. Я попытался добавить

for row in accessCur.columns(table='myTableName'.decode('utf-16-le')):

Я новичок в python .. поэтому я знаю, что мой синтаксис неверен.

В итоге я изменил код на следующий, и это рабочий:

    sqlColumns = 'SELECT * FROM Mytable where 1=0;'
    res = accessCur.execute(sqlColumns)
    columnlist = [tuple[0] for tuple in res.description]
    columnnames = ';'.join(columnlist) + ';'

1 Ответ

0 голосов
/ 06 мая 2020

Это известная проблема с драйвером Microsoft Access ODB C, описанная здесь:

https://github.com/mkleehammer/pyodbc/issues/328

Вы можете использовать функцию преобразователя вывода для обойти проблему:

def decode_sketchy_utf16(raw_bytes):
    s = raw_bytes.decode("utf-16le", "ignore")
    try:
        n = s.index('\u0000')
        s = s[:n]  # respect null terminator
    except ValueError:
        pass
    return s

# ...

prev_converter = cnxn.get_output_converter(pyodbc.SQL_WVARCHAR)
cnxn.add_output_converter(pyodbc.SQL_WVARCHAR, decode_sketchy_utf16)
col_info = crsr.columns("Clients").fetchall()
cnxn.add_output_converter(pyodbc.SQL_WVARCHAR, prev_converter)  # restore previous behaviour
...