Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 25, 2017 20:25:24

ViktorR
Зарегистрирован: 2017-06-25
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

Столкнулся с проблемой чтения / записи файлов в CSV формате.
Python ver. 3.6.1
matplotlib ver. 2.0.2
numpy ver. 1.13.0rc1
Пример из документации к matplotlib 2.0.2:

 import matplotlib.mlab as mplab
import numpy as np
r = mplab.csv2rec('somefile.csv', checkrows=0)
formatd = dict(
    weight = mplab.FormatFloat(2),
    change = mplab.FormatPercent(2),
    cost = mplab.FormatThousands(2),
    )
mplab.rec2csv(r, 'test.csv', formatd=formatd)

Содержимое файла somefile.csv
weight,change,cost
2100,2200,2300
31000,32000,33000

Ошибка:
Traceback (most recent call last):
File “C:\Python36\Work\444rrr.py”, line 9, in <module>
mplab.rec2csv(r, ‘test.csv’, formatd=formatd)
File “C:\Python36\lib\site-packages\matplotlib\mlab.py”, line 3283, in rec2csv
writer.writerow(header)
TypeError: a bytes-like object is required, not ‘str’

Замечание: Если открывать файл как текстовый, то все внешне нормально.
Но попытка прочитать файл test.csv (заменяем somefile.csv на test.csv) проваливается из-за ошибки.
Ошибка возникает, как я понимаю, из-за того, что при сохранении файла как текстового, в конец строк добавляются символы CRLF (файл текстовый и вроде так должно быть с CSV файлами). К сожалению в конце записанных строк находится другая комбинация - CR CRLF.
Аналогичная картина и с модулем CSV.
Возможно, что надо писать байт подобный объект, но как тогда преобразовать массив в такой объект?
Тип массива numpy.recarray.
Вопрос:
Есть ли у кого рабочий пример с функциями rec2csv() и csv2rec() или кто подскажет, как избавиться от такого рода ошибки?
Моя задача учебная - массивы записей (NumPy), чтение / запись CSV-файлов

Офлайн

#2 Июнь 26, 2017 00:08:37

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10002
Репутация: +  857  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

ViktorR
Есть ли у кого рабочий пример с функциями rec2csv() и csv2rec()
Похоже, что в mlab ошибка какая-то, так как нормальный csv-файл преобразуется в массив записей numpy, а потом для этого массива даже rec2txt() не работает.



Офлайн

#3 Июнь 26, 2017 02:50:58

scidam
Зарегистрирован: 2016-06-15
Сообщения: 288
Репутация: +  35  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

py.user.next
Похоже, что в mlab ошибка какая-то

Проблема эта начинается здесь
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/mlab.py#L3252
где файл для записи открывается в режиме записи байт ('b'),
т.е. чтобы не было этой ошибки, нужно в этой строке ‘wb’ исправить на ‘w’…. (т.к. потом используется csv writer)



ViktorR
Вообще, для таких операций с данными очень удобен Pandas, он поддерживает различные форматы, а также
DataFramы, которые удобней, чем recarray в numpy. И, наконец, numpy есть внутри pandas под видом pandas.np.

csv тоже будет работать если во writer подавать файл, открытый без ‘b’ аттрибута…



Отредактировано scidam (Июнь 26, 2017 02:55:00)

Офлайн

#4 Июнь 26, 2017 03:38:21

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10002
Репутация: +  857  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

scidam,
На втором питоне сработал код из первого сообщения, а на третий питон они его не допортировали, видимо.



Отредактировано py.user.next (Июнь 26, 2017 03:38:56)

Офлайн

#5 Июнь 26, 2017 10:08:21

ViktorR
Зарегистрирован: 2017-06-25
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

Спасибо за пояснения и рекомендацию.
Установил pandas.
Будем продолжать исследование новых земель …

Офлайн

#6 Июнь 26, 2017 14:57:12

ViktorR
Зарегистрирован: 2017-06-25
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

scidam

csv тоже будет работать если во writer подавать файл, открытый без ‘b’ аттрибута…

Вот пример:
 import csv
input_file = open("pr.csv", "r")
rdr = csv.reader(input_file)
output_file = open("pr1.csv", "w")
wrtr = csv.writer(output_file)
for rec in rdr:
    try:
        rec[1] = int(rec[1]) + 1
    except:
        pass
    wrtr.writerow(rec)
input_file.close()
output_file.close()
Вот файл pr.csv:
name,number,text
a,1,something here
b,2,“one, two, three”
c,3,“no commas here”
Теперь посмотрите на концы строк файла pr1.csv. Я смотрел FAR'ом. Там - CR CRLF, см. вложение.
Что я не так делаю?

Прикреплённый файлы:
attachment pr1.png (14,6 KБ)

Офлайн

#7 Июнь 27, 2017 01:48:19

scidam
Зарегистрирован: 2016-06-15
Сообщения: 288
Репутация: +  35  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

Попробуйте в коде использовать такой вариант для csv writer`a

 wrtr = csv.writer(output_file, lineterminator='\n')

У меня не Windows, в точности не могу воспроизвести…

Офлайн

#8 Июнь 27, 2017 02:16:44

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10002
Репутация: +  857  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

В формате CSV строки должны заканчиваться на CRLF в любой системе и в любых программах. Поэтому при открытии таких файлов в питоне используют бинарный режим rb и wb, так как текстовый режим r и w может изменять концы строк. Ты можешь открыть csv-файл в текстовом режиме, только если есть гарантия, что при записи прочитанных данных будут правильные концы строк.

То есть, скорее всего, ты прочитал данные в бинарном режиме, а сохраняешь их обратно потом в текстовом. Поэтому при чтении все символы сохранились неизменными \r\n, а при записи \n преобразовался в \r\n. Сделай так, чтобы при чтении и записи режим был одинаковый.



Офлайн

#9 Июнь 27, 2017 09:46:09

ViktorR
Зарегистрирован: 2017-06-25
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

py.user.next

Сделай так, чтобы при чтении и записи режим был одинаковый.

Это не сложно проверить, код не столь велик:
варианты:
 Открываем  Пишем  Результат
    r         w         # см. выше
    r         wt        # --"--
    r         wb        # TypeError: a bytes-like object is required, not 'str'
    rt        w         # аналогично первому варианту
    rt        wb        # TypeError: a bytes-like object is required, not 'str'
    rt        wt        # аналогично первому варианту
    rb       (xx)       # _csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

1) Строки в CSV - файлах должны всегда заканчиваться комбинацией CRLF - RFC4180.
2) Так понимаю, что при чтении данных из файла концы строк (CRLF) обрезаются.
Они в данных ни к чему.
3) При записи в файл в хвост строк добавляется CR (\r), а при записи в текстовом режиме и CRLF.
При хранении строковых данных в их хвостах нет ни \r ни \r\n (исключаем ситуацию, когда пользователь сам их туда вставил). Полагаю, что строки - нуль-терминированные.
Для окончательной проверки мне нужно понять, как строку, состоящую из полей разного типа (строки, целые), а еще лучше - массив записей, превратить в bytes-like object, см. первый пост.
4) Вообще то не очень понятно, почему режим чтения должен быть завязан на режим записи. Ну разве что лишь это особенность Python. Но в этом сильно сомневаюсь.

PS: У меня windows.
PSS: Чтение и запись с pandas получились. Пока проверяю как тут работать с массивами записей.

Отредактировано ViktorR (Июнь 27, 2017 09:54:40)

Офлайн

#10 Июнь 27, 2017 13:41:23

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10002
Репутация: +  857  -
Профиль   Отправить e-mail  

matplotlib.mlab / NumPy запись и чтение CSV файлов - rec2csv и csv2rec

ViktorR
r w # см. выше
Файл какой вводишь?

Не надо t вставлять, там всего два режима, а t используется просто для ясности.

ViktorR
2) Так понимаю, что при чтении данных из файла концы строк (CRLF) обрезаются.
Они читают через обычный файловый read() и пишутся через обычный файловый write() внутри csv, и вот в этих методах и происходят преобразования текстового режима (не только концы строк). Функции модуля csv никак на это не влияют. При чтении в текстовом режиме CRLF преобразуется в LF, а при записи в текстовом режиме LF преобразуется в CRLF (это для винды). Внутри питона у тебя LF. Но когда файл открывается в бинарном режиме, тогда все преобразования отменяются и байты читаются и пишутся так, как они хранятся. Если там LF, то прочитается LF, если там CRLF, то прочитается CRLF, так как в байтовом режиме нет понятия строк в файле, есть просто поток байт. То же самое при записи обратно - что пишется, то и пишется.

ViktorR
3) При записи в файл в хвост строк добавляется CR (\r), а при записи в текстовом режиме и CRLF.
При записи может добавляться CR, когда это на маке происходит.
Если же ты пишешь CRLF в текстовом режиме под виндой, то питон не воспринимает CRLF как конец строки, потому что для питона конец строки - это LF, поэтому он берёт этот LF и преобразует в CRLF, так у тебя получается CRCRLF при выводе в файл.



Отредактировано py.user.next (Июнь 27, 2017 13:44:03)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version