Переносимый способ записи 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'])