Unwanted characters when appending a newline in python3

Question:

I am appending newline to file if it doesn’t exist but it appending unwanted characters.

Input file:

abc

Code to append newline if it does exist:

with open(file_location, 'r') as file:
        data = file.read()
        if not data.endswith('n'):
            with open(file_location, 'a') as newline_file:
                writer = csv.writer(newline_file)
                writer.writerow('n')

or alternatively:

with open(local_file_location, 'r') as file:
        data = file.read()
        if not data.endswith('n'):
            with open(local_file_location, 'a') as newline_file:
                writer = csv.writer(newline_file)
                writer.writerow("n")

Giving the output below:

abc"
"

I do not want these:

""

I want the output below:

abc

How can I achieve this also let me know what I am doing wrong.

Asked By: lostSoul

||

Answers:

You wrote a newline as if it were a row of data, so it got quoted to keep it treated as part of the data, not the end of a row (it’s treating the str as an iterable of its characters, where each character is a separate field, exactly as if you called writer.writerow(["n"])). If you want to make it write the end of a row without writing any fields, pass an empty iterable, e.g.:

writer.writerow([])

Skipping the csv module is a naive solution you should avoid, as CSV is quite sensitive to how newlines are handled, so you do still want to use writerow here, rather than directly writeing to the underlying file.

On the subject of "CSV is quite sensitive to how newlines are handled" your code right now is wrong; the csv module is quite clear that you need to pass newline='' to the open calls so the csv.writer has complete control over how newlines are handled (for example, a newline in a field that’s part of the data might be written as 'n', while a newline separating records is 'rn' in common dialects).

So your code should be:

with open(file_location) as file:  # No newline='' needed since we want the translation
    data = file.read()[-1:]  # Don't store complete file data indefinitely; only care about last character
# May as well remove from with above, we don't need the file to remain open
if not data.endswith('n'):
    # Use newline='' so csv module controls how end of record is written
    with open(file_location, 'a', newline='') as newline_file:
        writer = csv.writer(newline_file)
        writer.writerow([])  # [] can be replaced with () or '' or any empty iterable if you prefer; [] is easier to see, () is probably fastest by a hair
Answered By: ShadowRanger
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.