Переносимый способ записи csv файла в python 2 или python 3
В моем окне Windows я обычно делал это в python 2, чтобы написать файл csv:
import csv
f = open("out.csv","wb")
cr = csv.writer(f,delimiter=';')
cr.writerow(["a","b","c"])
f.close()
Теперь, когда python 3 запрещает писать текстовые файлы как двоичные, этот фрагмент кода больше не работает. Это работает:
import csv
f = open("out.csv","w",newline='')
cr = csv.writer(f,delimiter=';')
cr.writerow(["a","b","c"])
f.close()
Проблема: параметр newline
неизвестен Python 2.
Конечно, опускание новой строки приводит к созданию файла csv со слишком большим количеством символов \r
, поэтому неприемлемым.
В настоящее время я выполняю обратный совместимый процесс для постепенной миграции из python 2 в python 3.5
Во всех моих модулях есть много этих утверждений.
Мое решение заключалось в встраивании кода в пользовательский модуль, а пользовательский модуль возвращал объект-обработчик + объект-автор. Проверка версии python выполняется внутри модуля, что позволяет любому модулю, использующему мой модуль, работать с любой версией python без чрезмерного взлома.
Есть ли лучший способ?
Ответы
Ответ 1
В Windows я нашел способ python 2 и 3, чтобы он менял параметр csv lineterminator
(который по умолчанию имеет значение "\r\n"
, что делает слишком большим \r
, когда файл открыт в текстовом режиме в Windows)
import csv
with open("out.csv","w") as f:
cr = csv.writer(f,delimiter=";",lineterminator="\n")
cr.writerow(["a","b","c"])
cr.writerow(["d","e","f"])
cr.writerow(["a","b","c"])
cr.writerow(["d","e","f"])
Независимо от версии python, это создаст файл csv без печально известных "пустых строк".
Единственный недостаток заключается в том, что в Linux этот метод создавал бы \r
-free файлы, что, возможно, не стандартное (хотя файлы по-прежнему правильно отображаются в excel, нет пустых строк и еще несколько строк:))
проблема сохраняется на 3.6.2 (просто проверил себя, как будто я должен был когда-нибудь)
Ответ 2
Для чтения и записи csv файлов я также не нашел лучшего способа - однако я бы инкапсулировал в отдельную функцию, как показано ниже. Преимущество состоит в том, что логика находится в одном месте, а не дублируется, если требуется больше одного раза.
import csv
import sys
def open_csv(filename, mode='r'):
"""Open a csv file in proper mode depending on Python verion."""
return(open(filename, mode=mode+'b') if sys.version_info[0] == 2 else
open(filename, mode=mode, newline=''))
with open_csv('out.csv', 'w') as f:
writer = csv.writer(f, delimiter=';')
writer.writerow([1, 2, 3])
writer.writerow(['a', 'b', 'c'])