Почему csv.reader с TextIOWrapper включает символы новой строки?

У меня есть две функции: одна загружает отдельные файлы CSV, а другая загружает zip-архив с несколькими файлами CSV.

Функция download_and_process_csv корректно работает с response.iter_lines(), которая, похоже, удаляет символы новой строки.

«Курица, вода, кукурузная мука, соль, декстроза, сахар, фосфат натрия, эриторбат натрия, нитрит натрия. Произведено на предприятии, где присутствуют аллергены, такие как яйца, молоко, соя, пшеница, горчица, глютен, овес, молочные продукты».

Функция download_and_process_zip, похоже, по какой-то причине включает символы новой строки (\n\n). Я пробовал newline='' в io.TextIOWrapper, но он просто заменяет его на \r\n.

«Курица, вода, кукурузная мука, соль, декстроза, сахар, фосфат натрия, эриторбат натрия, нитрит натрия. \n\nПроизведено на предприятии, где присутствуют аллергены, такие как яйца, молоко, соя, пшеница, горчица, глютен, овес, молочные продукты».

Есть ли способ изменить download_and_process_zip так, чтобы символы новой строки были исключены/заменены, или мне придется перебирать все строки и вручную заменять символы?

@request_exceptions
def download_and_process_csv(client, url, model_class):
    with closing(client.get(url, stream=True)) as response:
        response.raise_for_status()
        response.encoding = 'utf-8'
        reader = csv.reader(response.iter_lines(decode_unicode=True))
        process_copy_from_csv(model_class, reader)


@request_exceptions
def download_and_process_zip(client, url):
    with closing(client.get(url, stream=True)) as response:
        response.raise_for_status()

        with io.BytesIO(response.content) as buffer:
            with zipfile.ZipFile(buffer, 'r') as z:
                for filename in z.namelist():
                    base_filename, file_extension = os.path.splitext(filename)
                    model_class = apps.get_model(base_filename)
                    if file_extension == '.csv':
                        with z.open(filename) as csv_file:
                            reader = csv.reader(io.TextIOWrapper(
                                csv_file,
                                encoding='utf-8',
                                # newline='',
                            ))
                            process_copy_from_csv(model_class, reader)

возможно, проверьте, что у вас есть в переменных, прежде чем использовать TextIOWrapper - возможно, проблема в другом месте. ИЛИ, может быть, вы могли бы читать как bytes вместо string

furas 21.06.2024 22:35
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
1
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я поигрался с фиктивным сервером, который обслуживает этот CSV-файл:

"foo
bar"

CSV содержит одно поле "foo\nbar" в одной строке. Я называю новую строку в данных встроенной новой строкой.

Когда я использую метод iter_content для объекта Response:

print("Getting CSV")
resp = requests.get("http://localhost:8999/csv")
x = resp.iter_content(decode_unicode=True)

reader = csv.reader(x)
for row in reader:
    print(row)

Я получаю правильный вывод: выводится одна строка с одним полем данных:

Getting CSV
['foo\nbar']

Если я изменю iter_content на iter_lines, я получу неправильный результат:

Getting CSV
['foobar']

Судя по названию, я подозреваю, что iter_lines ищет любую последовательность символов, подобную новой строке, и останавливается на ней, прежде чем передать строку программе чтения csv (без новой строки), и поэтому встроенная новая строка эффективно удаляется. Я не могу говорить о вашем результате, когда новая строка была заменена пробелом... замены не происходит, просто эффективно удаляется.

Этот популярный SO, Использовать запросы Python для загрузки CSV, задает общий вопрос о загрузке CSV с помощью модуля запросов, но каждый ответ, кажется, адаптирован к тому факту, что рассматриваемый CSV не содержит встроенных символов новой строки, и поэтому там много ответов с iter_lines. Я не знаю, когда в запросы была добавлена ​​функция iter_content(), но об этом не упоминается ни в одном ответе.

Что касается замены пробелом, это моя ошибка - на самом деле символы новой строки удаляются. Я не внимательно присмотрелся, так как даже в моем примере перед символами новой строки есть пробел ' \n\n'

bdoubleu 26.06.2024 13:28

Другие вопросы по теме