Время прочтения: 3 мин.
Часто в работе нашего подразделения мы сталкиваемся с неприятной особенностью выгрузок CSV через инструмент PLSQL Developer – «сохранение в файл csv результата выполнения запроса».
Для дальнейшего анализа выгруженный файл csv обычно требуется загрузить в pandas.dataframe или в другую СУБД.
При попытке загрузки файла мы сталкиваемся с неприятными ошибками вроде нечитаемых символов, которые pandas не может соотнести с таблицей кодировки:
OSError: Initializing from file failed.
Исследуем вопрос, проведем анализ данных csv файла.
Прочитаем несколько срок из файла и выведем результат в консоль:
Код:
if __name__ == '__main__':
with open(r'C:\Users\user\Desktop\editOBScsv\1.csv', 'r', encoding='utf-8',
errors='ignore') as fo:
c = 0
for row in fo:
print(row)
c += 1
if c == 2:
break
— в данном случае указываем обязательный атрибут errors=’ignore’, который помогает игнорировать символы, не совпадающие с таблицей кодировки.
Вывод:
i?"ID кредита";"Сумма кредита….
"363092205X474";"2505600,00
Вывод в консоль в бинарном варианте чтения:
if __name__ == '__main__':
with open(r'C:\Users\Desktop\editOBScsv\нулевые графики.csv', 'rb') as fo:
c = 0
for row in fo:
print(row)
c += 1
if c == 1:
break
Вывод:
b'i\xbb?"ID \xd0\xba\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb8\xd1\x82\xd0\xb0";"\xd0\xa1\xd1\x83\xd0\xbc\xd0\xbc\xd0\xb0 \xd0\xba\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb8\xd1\x82\xd0\xb0";"\
Обратите внимание на первые 2 символа ‘i?’ (бинарный вариант i\xbb?). Именно они мешают методу pandas.read_csv корректно прочитать файл в DataFrame, а так же препятствуют загрузки файла в СУБД.
Далее рассмотрим три варианта решения.
Вариант первый
Если файл размера до 1.2 ГБ – файл открывается стандартным блокнотом.
Решение: Открыть файл – удалить первые два символа – сохранить и использовать в pandas/СУБД.
НО! Файлы более 1.2ГБ, блокнот, Notepad ++ — не откроют.
Вариант второй
Установить навороченный текстовый тру редактор, например – EmEditor работающий с большими текстовыми файлами. Открыть файл – удалить первые два символа – сохранить и использовать в pandas/СУБД.
Вариант третий для знающих Python
Csv – это текстовый файл, последовательность символов.
Решение, предложенное ниже использует встроенные библиотеки. Оно заключается в построчном чтении строк, при этом первая строка обрезается с левой стороны на 2 символа следующей конструкцией row = row[2:].
На выходе получаем обработанный файл, сохраненный в указанной директории.
pathRead – указываем путь к файлу, содержащему недопустимые символы
pathWrite – указываем пусть сохранения обработанного файла Код:
import time
if __name__ == '__main__':
prTimeStart = time.process_time()
cf = 0
pathRead = r'C:\Users\Desktop\editOBScsv\нулевые графики.csv'
pathWrite = r'C:\Users\Desktop\editOBScsv\out.csv'
with open(pathRead, 'r', encoding='utf-8', errors='ignore') as fo:
with open(pathWrite, 'w', encoding='utf-8') as fw:
for row in fo:
cf += 1
print('Row counts = %d' % cf)
fo.seek(0)
print(f'Starting to copy and past rows in the new file..')
cf = 0
for row in fo:
if cf == 0:
print('First row before changing:\n%s' % row)
row = row[2:]
print('First row after changing:\n%s' % row)
cf += 1
fw.writelines(row)
print('End copy row in new file.')
print('Time executed copy/past = %f' % (time.process_time() - prTimeStart))
C:\Anaconda3\python.exe C:/Users/PycharmProjects/editODScsv.py
Row counts = 3696862
Starting to copy and past rows in the new file..
First row before changing:
i?"ID кредита";"Сумма кредита….
First row after changing:
"ID кредита";"Сумма кредита…..
End copy row in new file.
Time executed copy/past = 275.781250
Process finished with exit code 0
Обработанный файл можно использовать в pandas/СУБД.