python-mastery/Exercises/ex5_5.md
2023-07-16 20:21:00 -05:00

98 lines
3.9 KiB
Markdown

\[ [Index](index.md) | [Exercise 5.4](ex5_4.md) | [Exercise 5.6](ex5_6.md) \]
# Exercise 5.5
*Objectives:*
- Learn more about exception handling and logging
*Files Modified:* `reader.py`
In the `reader.py` file, there is a central function `convert_csv()` that does
most of the work. This function crashes if you run it on data with missing or
bad data. For example:
```python
>>> port = read_csv_as_dicts('Data/missing.csv', types=[str, int, float])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "reader.py", line 24, in read_csv_as_dicts
return csv_as_dicts(file, types, headers=headers)
File "reader.py", line 13, in csv_as_dicts
lambda headers, row: { name: func(val) for name, func, val in zip(headers, types, row) })
File "reader.py", line 9, in convert_csv
return list(map(lambda row: converter(headers, row), rows))
File "reader.py", line 9, in <lambda>
return list(map(lambda row: converter(headers, row), rows))
File "reader.py", line 13, in <lambda>
lambda headers, row: { name: func(val) for name, func, val in zip(headers, types, row) })
File "reader.py", line 13, in <dictcomp>
lambda headers, row: { name: func(val) for name, func, val in zip(headers, types, row) })
ValueError: invalid literal for int() with base 10: ''
>>>
```
## (a) Catching Exceptions
Instead of crashing on bad data, modify the code to issue a warning message
instead. The final result should be a list of the rows that were successfully
converted. For example:
```python
>>> port = read_csv_as_dicts('Data/missing.csv', types=[str, int, float])
Row 4: Bad row: ['C', '', '53.08']
Row 7: Bad row: ['DIS', '50', 'N/A']
Row 8: Bad row: ['GE', '', '37.23']
Row 13: Bad row: ['INTC', '', '21.84']
Row 17: Bad row: ['MCD', '', '51.11']
Row 19: Bad row: ['MO', '', '70.09']
Row 22: Bad row: ['PFE', '', '26.40']
Row 26: Bad row: ['VZ', '', '42.92']
>>> len(port)
20
>>>
```
Note: Making this change may be a bit tricky because of your previous use of the `map()`
built-in function. You may have to abandon that approach since there's no easy way to catch
and handle exceptions in `map()`.
## (b) Logging
Modify the code so that warning messages are issued using the `logging` module. In
addition, give optional debugging information indicating the reason for failure.
For example:
```python
>>> import reader
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> port = reader.read_csv_as_dicts('Data/missing.csv', types=[str, int, float])
WARNING:reader:Row 4: Bad row: ['C', '', '53.08']
DEBUG:reader:Row 4: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 7: Bad row: ['DIS', '50', 'N/A']
DEBUG:reader:Row 7: Reason: could not convert string to float: 'N/A'
WARNING:reader:Row 8: Bad row: ['GE', '', '37.23']
DEBUG:reader:Row 8: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 13: Bad row: ['INTC', '', '21.84']
DEBUG:reader:Row 13: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 17: Bad row: ['MCD', '', '51.11']
DEBUG:reader:Row 17: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 19: Bad row: ['MO', '', '70.09']
DEBUG:reader:Row 19: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 22: Bad row: ['PFE', '', '26.40']
DEBUG:reader:Row 22: Reason: invalid literal for int() with base 10: ''
WARNING:reader:Row 26: Bad row: ['VZ', '', '42.92']
DEBUG:reader:Row 26: Reason: invalid literal for int() with base 10: ''
>>>
```
\[ [Solution](soln5_5.md) | [Index](index.md) | [Exercise 5.4](ex5_4.md) | [Exercise 5.6](ex5_6.md) \]
----
`>>>` Advanced Python Mastery
`...` A course by [dabeaz](https://www.dabeaz.com)
`...` Copyright 2007-2023
![](https://i.creativecommons.org/l/by-sa/4.0/88x31.png). This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)