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.
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 write
ing 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
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.
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 write
ing 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