Удалите возврат каретки/перевод строки из записей базы данных, прежде чем они будут записаны в csv

У меня есть следующий код, который читает строки из базы данных и записывает соответствующие результаты в файл csv. Проблема, с которой я сталкиваюсь, заключается в том, что иногда в некоторых полях в разных строках происходит возврат каретки/перевод строки, из-за чего файл csv становится непригодным для использования из-за наличия фиктивных строк.

Например, вот пример того, что происходит, когда в данных SQL есть возврат каретки/перевода строки, и как это влияет на файл. ... Пример содержимого испорченного файла:

field1|field2|field3|field4|field5
value 1|value 2|value 3|value 4|value 5
value 1|value 2|value 3|value 4|value 5
value 1|value 2|val
ue 3|value 4|value 5
value 1|value 2|value 3|va
lue 4|value 5

Вот код, который записывает результаты SQL-запроса в выходной файл. То, что я пытаюсь сделать, это удалить любые результаты, которые имеют возврат каретки/перевод строки.

    '''
    While loop to read each row.  if compares row[2] (updated) against the last record processed
    '''
    latest = params #Declare 'latest' variable for consumption by while loop
    while row:
        if row[2] > latest:
            latest = row[2]
        logger.debug("[%s] - Writing row %s", correlationId, row)
        writer.writerow(row)
        row = cursor.fetchone()

    logger.info("[%s] - last letter date %s " % (correlationId, lastProcessed))
    lastProcessedLog = open(LAST_PROCESSED_LOGFILE , 'wt')
    lastProcessedString = str(latest)
    lastProcessedString = lastProcessedString[0:19]
    lastProcessedLog.write(lastProcessedString)
    lastProcessedLog.close()

    conn.close()
    ofile.close()
    logger.info("[%s] - Copying %s to root for loadBackflow as %s", correlationId, writeFile, outfile)
    shutil.copyfile(writeFile, outfile)
    logger.info("[%s] - Moving %s to completion folder %s", correlationId, writeFile, completionFolder)
    shutil.move(writeFile, completionFolder)

Я попытался изменить строку write.write(row), чтобы включить замену, но получаю сообщение об ошибке. Точно так же я получаю ошибки при попытке использовать замену с помощью row = row.replace("\r\n", "")... Я вставил свои попытки и соответствующие ошибки ниже.

Любые идеи о том, как я могу удалить возвраты каретки/переводы строк во время их чтения из результатов SQL-запроса в файл данных, очень ценятся.

Заранее спасибо! :)

# Attempt1:
writer.writerow(row).replace("\r\n", "")
# Error:
Unexpected error: 'NoneType' object has no attribute 'replace'

# Attempt2:
row = row.replace("\r\n", "")
#Error:
Unexpected error: 'tuple' object has no attribute 'replace'

#Attempt3:
row = row.replace("\r", "")
row = row.replace("\n", "")
#Error:
Unexpected error: 'tuple' object has no attribute 'replace'

person Tony Nesavich    schedule 14.04.2015    source источник
comment
Как узнать, принадлежит ли строка следующей строке, а не является ли она полной строкой?   -  person TigerhawkT3    schedule 14.04.2015


Ответы (2)


Программирование путем перестановки — хорошо известный антипаттерн... db.cursor.fetchone() возвращает tuple, что — как ошибку сообщение говорит вам - не имеет метода replace() (какова будет семантика (1, 2, 3).replace("a string", "another string") ?), а csv.Writer.writerow() возвращает None (и поскольку он уже записал строку, какой смысл пытаться изменить ее позже?).

Итак, короче говоря, у вас есть два варианта:

  1. изменить строки в строке перед передачей в writerow()
  2. используйте формат csv, который позволяет вам избегать новых строк

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

Если это определенно не вариант, решение № 1 требует немного больше работы, поскольку кортежи и строки неизменяемы:

def preprocess_item(item):
    if isinstance(item, str):
        return item.replace("\n", " ").replace("\r", " ")    
    return item

def preprocess_row(row):
    return tuple(preprocess_item(item) for item in row)

def yourfunction(whatever):
    ### some code here
    row = cursor.fetchone()
    row = preprocess_row(row)
    writer.writerow(row)
person bruno desthuilliers    schedule 14.04.2015
comment
Спасибо Бруно, я думаю, что это может быть лучше всего. Однако я вижу следующую ошибку: - person Tony Nesavich; 15.04.2015
comment
Неожиданная ошибка: объект NoneType не является итерируемым - person Tony Nesavich; 15.04.2015
comment
''' Цикл while для чтения каждой строки. if сравнивает row[2] (обновлено) с последней обработанной записью ''' last = params # Объявить 'последнюю' переменную для использования циклом while def preprocess_item(item): if isinstance(item, str): return item.replace( \r\n, ) #return item.replace(\n, ).replace(\r, ) вернуть элемент - person Tony Nesavich; 15.04.2015
comment
def preprocess_row(row): вернуть кортеж(preprocess_item(item) для элемента в строке) while row: if row[2] › last: #row = cursor.fetchone() last = row[2] logger.debug([%s ] - Запись строки %s, CorrelationId, row) row = cursor.fetchone() row = preprocess_row(row) Writer.writerow(row) - person Tony Nesavich; 15.04.2015

Метод fetchone() возвращает строку в виде кортежа. Он может содержать более одного значения поля в зависимости от таблицы. Вы не можете выполнить строковый метод замены для кортежа, и это объясняет ошибку, которую вы видите. Я не знаю структуру кортежа, возвращаемого fetchone, поэтому предположу, что это первый элемент.

stripped_row = row[0].replace("\r", "")
stripped_row = stripped_row.replace("\n", "")
person sid1408    schedule 14.04.2015