patternpythonMinor
csview: A tiny utility to view csv files
Viewed 0 times
csviewcsvutilityviewtinyfiles
Problem
Seeing a csv in table form is nicer then viewing it as row text, for example the csv from Calculate food company sales for the year (with headers added by me) looks much nicer in this table form than in plain-text:
To view a
The code is short because the task is simple, but I feel like it could be written better:
Kind
Brand
Sales in 2014
Sales in 2015
Cereal
Magic Balls
2200
2344
Cereal
Kaptain Krunch
3300
3123
Cereal
Coco Bongo
1800
2100
Cereal
Sugar Munch
4355
6500
Cereal
Oats n Barley
3299
5400
Sugar Candy
Pop Rocks
546
982
Sugar Candy
Lollipop
1233
1544
Sugar Candy
Gingerbud
2344
2211
Sugar Candy
Respur
1245
2211
Chocolate
Coco Jam
3322
4300
Chocolate
Larkspur
1600
2200
Chocolate
Mighty Milk
1234
2235
Chocolate
Almond Berry
998
1233
Condiments
Peanut Butter
3500
3902
Condiments
Hot Sauce
1234
1560
Condiments
Jelly
346
544
Condiments
Spread
2334
5644
To view a
.csv file, I just translate it into HTML and call the browser on it.The code is short because the task is simple, but I feel like it could be written better:
"""
This utility shows a csv file in table format
by translating it to html and calling the browser on the newly created file.
The html file is not deleted after being viewed
and has name `original_file.split('.')[0] + '.html'`
Example usage:
python3 csview.py example.csv
"""
import webbrowser
import sys
def csv_to_html(csv):
START = '''\n\n'''
END = ''''''
lines = [line for line in csv.split("\n") if line]
html_lines = ["" + lines[0].replace(',', '\n') + ''] +\
["" + line.replace(',', '\n') for line in lines[1:]]
body = '\n' + '\n\n\n\n'.join(html_lines)
return START + body + END
if __name__ == "__main__":
html_filename = sys.argv[1].split('.')[0] + '.html'
with open(html_filename, "w+") as out_file:
with open(sys.argv[1]) as in_file:
out_file.write(csv_to_html(in_file.read()))
webbrowser.open(html_filename)Solution
Constants
They are better defined outside of functions; there is no need in reinitializing them each call.
Also they are not balanced, fixing it will avoid a weird
Files management
Just in case the path of the input file contained a dot, I recommend you use
Also you should try to open the input file before the ouput one. Just in case an error happen during the access to the file, you won't create an empty output file.
And since you're dealing with CSV files, why not use the
Wrap stuff into tags
Since you're outputing HTML, it may be a better idea to build it as such: by wrapping stuff into tags.
You could define a
Proposed improvements
They are better defined outside of functions; there is no need in reinitializing them each call.
Also they are not balanced, fixing it will avoid a weird
body = '\n' + ....Files management
Just in case the path of the input file contained a dot, I recommend you use
rsplit('.', 1).Also you should try to open the input file before the ouput one. Just in case an error happen during the access to the file, you won't create an empty output file.
And since you're dealing with CSV files, why not use the
csv module? It will allow you to handle edge-case data (such as fields containing comas or newlines) easily.Wrap stuff into tags
Since you're outputing HTML, it may be a better idea to build it as such: by wrapping stuff into tags.
You could define a
PATTERN = "{{}}" and a formatter:def formatter(tag):
return PATTERN.format(tag=tag).formatmap that formatter at will to wrap stuff into tags.Proposed improvements
import webbrowser
import sys
import csv
PATTERN = "{{}}"
def formatter(tag):
return PATTERN.format(tag=tag).format
def csv_to_html(csv_file):
reader = csv.reader(csv_file)
header = formatter('tr')(
'\n'.join(map(formatter('th'), next(reader)))
)
data = '\n'.join(
map(formatter('tr'),
'\n'.join(map(formatter('td'), row))
for row in reader
)
)
return formatter('table')('\n'.join((header, data)))
if __name__ == "__main__":
csv_filename = sys.argv[1]
html_filename = csv_filename.rsplit('.', 1)[0] + '.html'
with open(csv_filename) as in_file:
with open(html_filename, "w+") as out_file:
out_file.write(csv_to_html(in_file))
webbrowser.open(html_filename)Code Snippets
def formatter(tag):
return PATTERN.format(tag=tag).formatimport webbrowser
import sys
import csv
PATTERN = "<{tag}>{{}}</{tag}>"
def formatter(tag):
return PATTERN.format(tag=tag).format
def csv_to_html(csv_file):
reader = csv.reader(csv_file)
header = formatter('tr')(
'\n'.join(map(formatter('th'), next(reader)))
)
data = '\n'.join(
map(formatter('tr'),
'\n'.join(map(formatter('td'), row))
for row in reader
)
)
return formatter('table')('\n'.join((header, data)))
if __name__ == "__main__":
csv_filename = sys.argv[1]
html_filename = csv_filename.rsplit('.', 1)[0] + '.html'
with open(csv_filename) as in_file:
with open(html_filename, "w+") as out_file:
out_file.write(csv_to_html(in_file))
webbrowser.open(html_filename)Context
StackExchange Code Review Q#119090, answer score: 4
Revisions (0)
No revisions yet.