Python skips line when printing to CSV - python

I am trying to create .csv file.
For some reason it skips line before printing entry.
Here is the output
But here is what I need
Below is code. Apparently if line != "": doesn't work
import csv
#-----------------------------------
def csv_writer(data,path):
"""
Write data to a CSV file path
"""
with open(path, "w") as csv_file:
writer = csv.writer(csv_file, delimiter=',')
for line in data:
if line != "":
writer.writerow(line)
#-----------------------------------
if __name__ == "__main__":
data = ["first_name,last_name,city".split(","),
"Tyrese,Hirthe,Strackeport".split(","),
"Jules,Dicki,Lake Nickolasville".split(","),
"Dedric,Medhurst,Stiedemannberg".split(",")
]
path = "output.csv"
csv_writer(data,path)

Some python versions (on windows) have an issue with that with open(path, "w") as csv_file:. A spurious carriage return char is inserted, creating a blank line after each line.
You have to add newline="" as stated in the documentation. Python 3:
with open(path, "w",newline="") as csv_file:
writer = csv.writer(csv_file, delimiter=',')
As for python 2:
with open(path, "wb") as csv_file:
writer = csv.writer(csv_file, delimiter=',')
see also:
portable way to write csv file in python 2 or python 3
csv writer expected byte like and space between rows
(note that latest Python versions on Windows don't need this anymore, but the documentation continues to state it)

When you open the file you need to pass the keyword argument newline with a blank string. This will prevent the newlines being added between rows. Your function should be:
def csv_writer(data,path):
"""
Write data to a CSV file path
"""
with open(path, "w", newline = '') as csv_file:
writer = csv.writer(csv_file, delimiter=',')
for line in data:
if line:
writer.writerow(line)
Note that this is only an issue on Windows.

Related

Read and write CSV file in Python

I'm trying to read sentences in a csv file, convert them to lowercase and save in other csv file.
import csv
import pprint
with open('dataset_elec_4000.csv') as f:
with open('output.csv', 'w') as ff:
data = f.read()
data = data.lower
writer = csv.writer(ff)
writer.writerow(data)
but I got error "_csv.Error: sequence expected". What should I do?
*I'm a beginner. Please be nice to me:)
You need to read over your input CSV row-by-row, and for each row, transform it, then write it out:
import csv
with open('output.csv', 'w', newline='') as f_out:
writer = csv.writer(f_out)
with open('dataset_elec_4000.csv', newline='') as f_in:
reader = csv.reader(f_in)
# comment these two lines if no input header
header = next(reader)
writer.writerow(header)
for row in reader:
# row is sequence/list of cells, so...
# select the cell with your sentence, I'm presuming it's the first cell (row[0])
data = row[0]
data = data.lower()
# need to put data back into a "row"
out_row = [data]
writer.writerow(out_row)
Python contains a module called csv for the handling of CSV files. The reader class from the module is used for reading data from a CSV file. At first, the CSV file is opened using the open() method in ‘r’ mode(specifies read mode while opening a file) which returns the file object then it is read by using the reader() method of CSV module that returns the reader object that iterates throughout the lines in the specified CSV document.
import csv
# opening the CSV file
with open('Giants.csv', mode ='r')as file:
# reading the CSV file
csvFile = csv.reader(file)
# displaying the contents of the CSV file
for lines in csvFile:
print(lines)

Deleting a row from a csv(Python)

So, I'm trying to make a function to delete a row from my csv depending on the Name given by the parameter.
Original File:
Janet,5,cats
Wilson,67,dogs
Karen,8,mice
John,12,birds
My Code:
csv_remove("Karen")
Intended File:
Janet,5,cats
Wilson,67,dogs
John,12,birds
However, when I execute my code, I get weird newlines everywhere.
Janet,5,cats
Wilson,67,dogs
John,12,birds
Here is the full code:
def csv_remove(name):
element_list = []
with open(csv_path, 'r') as j:
csv_file = csv.reader(j)
for row in csv_file:
element_list.append(row)
if row[0] == name:
element_list.remove(row)
with open(csv_path, 'w') as j:
csv_file = csv.writer(j)
csv_file.writerows(element_list)
csv_remove("Karen")
Read the documentation. When opening a file for writing using the csv-module you need to
supply newline="":
Source: https://docs.python.org/3/library/csv.html#csv.writer
csv.writer(csvfile, dialect='excel', **fmtparams)
Return a writer object responsible for converting the user’s data into delimited strings on the given file-like object. csvfile can be any object with a write() method. If csvfile is a file object, it should be opened with newline=''
The csv-module handles newlines itself. If you do not specify newline='' for the opened file, it will muck up the line endings and you end up with empty lines in it.

Python CSV writer script syntax

Who wants to help out a newbie? I keep getting either Indent errors or when I manage correct indentation I end up with an IO error because the file is already automatically closed by the Open With. What am I doing wrong?
This is my script;
import csv
infile = ('Test')
with open(infile+'.txt') as csvfile, open('output.csv', 'w', encoding='utf-8') as outfile:
lines = sorted(set(line.strip('\n').lower() for line in csvfile))
for line in lines:
writer = csv.writer(outfile, lineterminator='\n', quoting=csv.QUOTE_ALL)
writer.writerow(line)
Thanks for helping me out!
Indent the code to write out under the with statement.
You had a few spaces in there as well that were throwing out the indentation. I flattened your code then indented it out. You'll probably have to either open as read-write or open once to read and then once to write.
import csv
infile = ('Test')
with open(infile+'.txt') as csvfile, open('output.csv', 'w', encoding='utf-8') as outfile:
lines = sorted(set(line.strip('\n').lower() for line in csvfile))
for line in lines:
writer = csv.writer(outfile, lineterminator='\n', quoting=csv.QUOTE_ALL)
writer.writerow(line)
I edited the formatting on the original question. If my edit did not somehow mess things up, the likely issue is that by opening and closing both infile and outfile in the same with block you have already closed outfile when you want to write to it.
If you rearrange it like this it may be more predictable
import csv
infile = ('Test')
with open(infile+'.txt') as csvfile:
lines = sorted(set(line.strip('\n').lower() for line in csvfile))
with open('output.csv', 'w', encoding='utf-8') as outfile:
writer = csv.writer(outfile, lineterminator='\n', quoting=csv.QUOTE_ALL)
for line in lines:
writer.writerow(line)

Using r+ mode to read and write into the same file

I have a script that successfully removes a column from a csv file. Currently it does this by creating a new file. I want it to write to the original file rather than create a new one.
I’ve tried this by using the r+ mode for open but it’s not working how I want. See notes below. I think r+ mode is the one I need but I’m struggling to find working examples to learn from.
my code:
import csv
in_file = "Path to Source"
out_file = "Path to Result"
with open(in_file, 'r', newline='') as inf, \
open(out_file, 'w', newline='') as outf:
reader = csv.reader(inf)
writer = csv.writer(outf)
for r in reader:
writer.writerow((r[0],r[1],r[2],r[3],r[4],r[5],r[6]))
attempt using r+ mode:
with open(in_file, 'r+', newline='') as inf:
reader = csv.reader(inf)
writer = csv.writer(inf)
for r in reader:
writer.writerow((r[0],r[1],r[2],r[3],r[4],r[5],r[6]))
This fails with the error list index out of range
From what I see, as the reader reads, the writer writes. On the same file.
Files have a 'cursor', i.e. a current position upon which they are read from/written to.
So the writer is overwriting the next row in the file after the one the reader has just read, with catastrophic consequences on the following readings.
I think the first approach is the best one: create a new file and then rename it (the original input file is deleted automatically)
import csv, os
in_file = "Path to Source"
out_file = "Path to Result"
with open(in_file, 'r', newline='') as inf, \
open(out_file, 'w', newline='') as outf:
reader = csv.reader(inf)
writer = csv.writer(outf)
for r in reader:
writer.writerow(r[:7])
os.rename(out_file, in_file)

read and write on same csv file

I am trying to read and write on the same CSV file:
file1 = open(file.csv, 'rb')
file2 = open(file.csv, 'wb')
reader = csv.reader(file1)
writer = csv.writer(file2)
for row in reader:
if row[2] == 'Test':
writer.writerow( row[0], row[1], 'Somevalue')
My csv files are:
val1,2323,Notest
val2, 2323,Test
So basically if my row[2] value is Test I want to replace it with Some new value.
The above code gives me empty CSV files.
You should use different output file name. Even if you want the name to be the same, you should use some temporary name and finally rename file.
When you open file in 'w' (or 'wb') mode this file is "cleared" -- whole file content disappears. Python documentation for open() says:
... 'w' for only writing (an existing file with the same name will be erased), ...
So your file is erased before csv functions start parsing it.
You can't open a file in both read and write modes at once.
Your code could be modified as follows:-
# Do the reading
file1 = open(file.csv, 'rb')
reader = csv.reader(file1)
new_rows_list = []
for row in reader:
if row[2] == 'Test':
new_row = [row[0], row[1], 'Somevalue']
new_rows_list.append(new_row)
file1.close() # <---IMPORTANT
# Do the writing
file2 = open(file.csv, 'wb')
writer = csv.writer(file2)
writer.writerows(new_rows_list)
file2.close()
As Jason points out, if your CSV is too big for your memory, then you'll need to write to a different filename and then rename it. This will likely be a bit slower.
If your csv file is not big enough(to explode the memory), read it all into memory and close the file before open it in write mode.
Or you should consider writing to a new file rather than the same one.
It is not possible to open the same file in two different modes in python.You have to release one of the file pointers with file_name.close() before opening the file in another mode!

Categories