Skip to content

Commit 3179620

Browse files
committed
end of 3.6
1 parent e276705 commit 3179620

5 files changed

Lines changed: 118 additions & 114 deletions

File tree

Work/fileparse.py

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,87 @@
22
#
33
# Exercise 3.3
44
import csv
5+
import gzip
56

6-
def parse_csv(filename, select=None, types=None, has_headers=True, delimiter=',', silence_errors=True):
7+
def parse_csv(source, select=None, types=None, has_headers=True, delimiter=',', silence_errors=True):
78
'''
8-
Parse a CSV file into a list of records
9+
Parse an iterable into a list of records
910
'''
11+
if type(source) == str:
12+
raise RuntimeError("source must be iterable")
13+
1014
if select and not has_headers:
1115
raise RuntimeError("select argument requires column headers")
16+
17+
rows = csv.reader(source, delimiter=delimiter)
18+
19+
# Read the file headers
20+
if has_headers:
21+
headers = next(rows)
22+
start = 2
23+
else:
24+
headers = []
25+
start = 1
26+
27+
# If a column selector was given, find those names indices
28+
# Also narrow the set of headers as given
29+
if select:
30+
indices = [headers.index(colname) for colname in select] # [0, 1 ]
31+
headers = select
32+
else:
33+
indices = []
34+
35+
records = []
36+
for rownum, row in enumerate(rows, start=start):
1237

13-
with open(filename) as f:
14-
rows = csv.reader(f, delimiter=delimiter)
38+
if not row: # Skip rows with no data
39+
continue
40+
try:
41+
# Filter the row if specific columns were selected
42+
if indices:
43+
row = [ row[index] for index in indices ]
44+
45+
# Convert types if a list of types is provided
46+
if types:
47+
row = [func(val) for func, val in zip(types, row) ]
1548

16-
# Read the file headers
49+
except ValueError as e:
50+
if not silence_errors:
51+
print(f"Row {rownum}: Could not convert: {row}")
52+
print(f"Row {rownum}: Reason: {e}\n")
53+
continue
54+
55+
# print(list(zip(headers, row)))
1756
if has_headers:
18-
headers = next(rows)
19-
start = 2
20-
else:
21-
headers = []
22-
start = 1
23-
24-
# If a column selector was given, find indices of the specified columns.
25-
# Also narrow the set of headers used for resulting dictionaries
26-
if select:
27-
indices = [headers.index(colname) for colname in select] # [0, 1 ]
28-
headers = select
57+
record = dict(zip(headers, row))
2958
else:
30-
indices = []
31-
32-
records = []
33-
for rownum, row in enumerate(rows, start=start):
34-
if not row: # Skip rows with no data
35-
continue
36-
try:
37-
# Filter the row if specific columns were selected
38-
if indices:
39-
row = [ row[index] for index in indices ]
40-
41-
# Convert types if a list of types is provided
42-
if types:
43-
row = [func(val) for func, val in zip(types, row) ]
44-
45-
except ValueError as e:
46-
if not silence_errors:
47-
print(f"Row {rownum}: Could not convert: {row}")
48-
print(f"Row {rownum}: Reason: {e}\n")
49-
continue
50-
51-
# print(list(zip(headers, row)))
52-
if has_headers:
53-
record = dict(zip(headers, row))
54-
else:
55-
record = tuple(row)
56-
records.append(record)
59+
record = tuple(row)
60+
records.append(record)
5761

5862
return records
5963

60-
with open('.\\Data\\portfolio.csv') as f:
61-
d = parse_csv(f, types=[str, int, float])
6264

63-
print(d)
65+
66+
# with open('.\\Data\\portfolio.csv') as f:
67+
# d = parse_csv(f, types=[str, int, float])
68+
69+
# print(d)
70+
71+
72+
73+
# with gzip.open('.\\Data\\portfolio.csv.gz', 'rt') as f:
74+
# d = parse_csv(f, types=[str, int, float])
75+
76+
# print(d)
77+
78+
79+
80+
# lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
81+
# pf = parse_csv(lines, types=[str,int,float])
82+
# print(pf)
83+
84+
85+
6486

6587
# portfolio = parse_csv('.\\Data\\portfolio.csv', select=['name','shares'], types=[str, int])
6688
# print(portfolio)

Work/pcost.3.14.py

Lines changed: 0 additions & 17 deletions
This file was deleted.
File renamed without changes.

Work/pcost314.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# Exercise 3.14
3+
4+
from report import read_portfolio
5+
6+
def portfolio_cost(filename):
7+
''' Calculate total cost of portofolio '''
8+
9+
portfolio = read_portfolio(filename)
10+
return sum([i['shares'] * i['price'] for i in portfolio ])
11+
12+
13+
14+
15+
def main(argv):
16+
pf_file = argv[1]
17+
cost = portfolio_cost(pf_file)
18+
print(f'Total cost of portfolio: ${cost:0.2f}')
19+
20+
if __name__ == '__main__':
21+
import sys
22+
23+
if len(sys.argv) != 2:
24+
raise SystemExit(f'Usage: {sys.argv[0]} ' 'portfoliofile')
25+
26+
main(sys.argv)
27+

Work/report.py

Lines changed: 23 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,23 @@
11
# report.py
22
#
3-
# Exercise 2.4 - 2.12
3+
# Exercise 2.4 - 2.12 - 3.16
44
import csv
55
from pprint import pprint
66
from fileparse import parse_csv
77

88

9-
109
def read_prices(filename):
1110
"""Reads stock prices from a CSV file and returns a dictionary mapping stock names to prices."""
12-
# prices = {}
13-
# with open(filename, 'rt') as f:
14-
# rows = csv.reader(f)
15-
16-
# for row in rows:
17-
# if not row: # Skip empty rows
18-
# continue
19-
20-
# prices[row[0]] = float(row[1])
21-
prices = parse_csv(filename, types=[str,float], has_headers=False)
22-
11+
12+
with open(filename) as f:
13+
prices = parse_csv(f, types=[str,float], has_headers=False)
2314
return dict(prices)
2415

2516
def read_portfolio(filename):
26-
"""Reads a stock portfolio from a CSV file with handling for missing files."""
27-
# value = 0.0
28-
# data_list = []
17+
"""Reads a stock portfolio from a CSV file with handling for missing files and returns a list."""
2918

30-
# try:
31-
32-
# with open(filename, 'rt') as f:
33-
# rows = csv.reader(f)
34-
# headers = next(rows) # skip the header line
35-
36-
# for rownum, row in enumerate(rows, start=2):
37-
# # data_dict = {
38-
# # 'name': row[0],
39-
# # 'shares': int(row[1]),
40-
# # 'price': float(row[2])
41-
# # }
42-
# record = dict(zip(headers, row))
43-
# try:
44-
# record['shares'] = int(record['shares'])
45-
# record['price'] = float(record['price'])
46-
# # value += num_shares * price
47-
# data_list.append(record)
48-
49-
# except ValueError:
50-
# print(f'Line {rownum}: Bad line: {row}')
51-
52-
# return data_list, headers
53-
54-
# except FileNotFoundError:
55-
# print(f'Error: The file {filename} was not found.')
56-
# return None
57-
portfolio = parse_csv(filename, types=[str, int, float])
19+
with open(filename) as f:
20+
portfolio = parse_csv(f, types=[str, int, float])
5821
return portfolio
5922

6023
def make_report(portfolio, prices):
@@ -64,7 +27,7 @@ def make_report(portfolio, prices):
6427
name = stock['name']
6528
shares = int(stock['shares'])
6629
purchase_price = float(stock['price'])
67-
current_price = prices.get(name, 0.0)
30+
current_price = prices.get(name, 0.0) # this is why prices must be a dict, not a list
6831
gain_loss = (current_price - purchase_price)
6932
report.append((name, shares, current_price, gain_loss))
7033
return report
@@ -79,7 +42,7 @@ def print_report(report):
7942

8043
def portfolio_report(portfolio_file, prices_file):
8144
"""Generates and prints a portfolio report from given files."""
82-
45+
8346
curr_prices = read_prices(prices_file)
8447
portfolio = read_portfolio(portfolio_file)
8548

@@ -89,11 +52,20 @@ def portfolio_report(portfolio_file, prices_file):
8952
report = make_report(portfolio, curr_prices)
9053
print_report(report)
9154

92-
# portfolio_report('.\\Data\\portfoliodate.csv', '.\\Data\\prices.csv')
9355

56+
def main(argv):
57+
pf_file = argv[1]
58+
price_file = argv[2]
59+
60+
portfolio_report(pf_file, price_file)
61+
62+
63+
if __name__ == '__main__':
64+
import sys
65+
# print('hey this file is executed as main, not imported')
66+
if len(sys.argv) != 3:
67+
raise SystemExit(f'Usage: {sys.argv[0]} ' 'portfile pricefile')
68+
69+
main(sys.argv)
9470

9571

96-
# curr_prices = read_prices('.\\Data\\prices.csv')
97-
# portfolio_data = read_portfolio('.\\Data\\portfoliodate.csv')
98-
# report = make_report(portfolio_data[0], curr_prices)
99-
# print_report(report)

0 commit comments

Comments
 (0)