Запись строки в CSV с использованием экранирования строки в Python 3 - PullRequest
0 голосов
/ 25 сентября 2018

Работа в Python 3.7.

В настоящее время я извлекаю данные из API (API Qualys, выбирая отчет), чтобы быть точным.Он возвращает строку со всеми данными отчета в формате CSV, причем каждая новая строка обозначается экранированием '\ r \ n'.

(т. Е. 'Foo, bar, stuff \ r \ n, more stuff,данные, отчет \ r \ n и т. д. и т. д. и т. д. \ r \ n ')

У меня проблема с записью этой строки в файл CSV.Каждая итерация кода, которую я пробовал, записывает данные ячейку за ячейкой при просмотре в Excel с добавлением \ r \ n в любом месте строки в одной строке, а не в новой строке.

(т.е. | foo | bar | stuff \ r \ n | more stuff | data | report \ r \ n | etc | etc | etc \ r \ n |)

Я просто переключаюсь с2 к 3, так что я почти уверен, что это синтаксическая ошибка или ошибка с моим пониманием того, как python 3 обрабатывает новые разделители строк или что-то в этом роде, но даже после просмотра документации, здесь и постов в блоге, я просто не могу получить свойобойдите его, или я постоянно что-то упускаю.

текущий код:

def dl_report(id, title):
    data = {'action': 'fetch', 'id': id}
    res = a.request('/api/2.0/fo/report/', data=data)
    print(type(res)) #returns string

    #input('pause')
    f_csv = open(title,'w', newline='\r\n')
    f_csv.write(res)
    f_csv.close

но я также пробовал:

with open(title, 'w', newline='\r\n') as f:
    writer = csv.writer(f,<tried encoding here, no luck>)
    writer.writerows(res)

#anyone else looking at this, this didn't work because of the difference 
#between writerow() and writerows()

и у меня естьтакже пробовал различные способы объявления новой строки, такие как:

newline=''
newline='\n'
etc...

и различные другие итерации в этом направлении.Любые предложения или указания или ... что-нибудь на этом этапе было бы замечательно.

edit:

Хорошо, я продолжал работать над этим, и это вроде работает:

def dl_report(id, title):
data = {'action': 'fetch', 'id': id}
res = a.request('/api/2.0/fo/report/', data=data)
print(type(res)) #returns string

reader = csv.reader(res.split(r'\r\n'), delimiter=',')

with open(title, 'w') as outfile:
    writer = csv.writer(outfile, delimiter= '\n')
    writer.writerow(reader)

Но это уродливо и создает ошибки в выводеCSV (некоторые строки (менее 1%) не анализируются как строки CSV, возможно, это ошибка форматирования где-то ...), но более важно то, что он работает некорректно, когда в данных присутствует символ "\".

Мне бы очень хотелось, чтобы решение работало ... лучше?Более питон?более последовательно было бы неплохо ...

Есть идеи?

Ответы [ 4 ]

0 голосов
/ 26 сентября 2018

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

Это относительно простос использованием кодека unicode-escape (который также обрабатывает экранирование ASCII):

import codecs  # Needed for text->text decoding

# ... retrieve data here, store to res ...

# Converts backslash followed by r to carriage return, by n to newline,
# and so on for other escapes
decoded = codecs.decode(res, 'unicode-escape')

# newline='' means don't perform line ending conversions, so you keep \r\n
# on all systems, no adding, no removing characters
# You may want to explicitly specify an encoding like UTF-8, rather than
# relying on the system default, so your code is portable across locales
with open(title, 'w', newline='') as f:
    f.write(decoded)

Если полученные строки на самом деле заключены в кавычки (поэтому print(repr(s)) включает в себя кавычки на обоих концах), возможно, онипредназначен для интерпретации как строки JSON.В этом случае просто замените import и создание decoded на:

import json


decoded = json.loads(res)
0 голосов
/ 25 сентября 2018

Проверьте этот ответ:

Строка Python CSV в массив

Согласно документации CSVReader, он ожидает \ r \ n в качестве разделителя строк по умолчанию.Ваша строка должна нормально с ней работать.Если вы загрузите строку в объект CSVReader, вы сможете проверить стандартный способ ее экспорта.

0 голосов
/ 26 сентября 2018

В строках Python используется символ новой строки \n.Обычно \r\n преобразуется в \n, когда файл читается, а новая строка преобразуется \n или \r\n в зависимости от используемой по умолчанию системы и параметра newline= при записи.

Inваш случай, \r не был удален, когда вы читали его из веб-интерфейса.Когда вы открыли файл с помощью newline='\r\n', python расширил \n, как и предполагалось, но \r прошел, и теперь ваш neline - \r\r\n.Это можно увидеть, перечитав текстовый файл в двоичном режиме:

>>> res = 'foo,bar,stuff\r\n,more stuff,data,report\r\n,etc,etc,etc\r\n'
>>> open('test', 'w', newline='\r\n').write(res)
54
>>> open('test', 'rb').read()
b'foo,bar,stuff\r\r\n,more stuff,data,report\r\r\n,etc,etc,etc\r\r\n'

Поскольку у вас уже есть нужные окончания строк, просто напишите в двоичном режиме и пропустите преобразования:

>>> open('test', 'wb').write(res.encode())
54
>>> open('test', 'rb').read()
b'foo,bar,stuff\r\n,more stuff,data,report\r\n,etc,etc,etc\r\n'

Обратите внимание, что я использовал системную кодировку по умолчанию, но вы, вероятно, хотите стандартизировать кодировку.

0 голосов
/ 25 сентября 2018

Если я правильно понимаю ваш вопрос, вы не можете просто заменить строку? with open(title, 'w') as f: f.write(res.replace("¥r¥n","¥n"))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...