Traceback (most recent call last):
File "stock.py", line 10, in <module>
print(total_quantity(["item,quantity", "bolts,120", "nuts,80"]))
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "stock.py", line 6, in total_quantity
total += int(quantity)
~~~^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'quantity'int() tells you exactly what it could not convert. Three calls, and the message from the last one.
print(int("42")) # 42
print(int(" 42 ")) # 42 -- spaces around a number are fine
print(int("forty-two"))
# ValueError: invalid literal for int() with base 10: 'forty-two'
- The quotes are the evidence
Everything after the colon is the input, in quotes, exactly as int() received it. Spaces, capitals and stray characters all show, because it is the repr of the string.
- Search the input for it
Take the quoted text and look for it in the file or the list you passed in. It tells you which line was the problem without adding a single print.
- Ask whether it is data at all
A word where a number should be is usually not bad data. It is something that was never meant to be converted: a header, a total row, a comment.
The value in quotes at the end of the traceback is 'quantity'. Where in the input does that word appear?
It is the header, the first line of the file. The loop treats it as a data row and hands its second column to int().
Skip exactly the first line, by position: loop over lines[1:]. That works whatever the header says, and slicing an empty list is safe.
for line in lines[____:]: item, quantity = line.split(",") total += ____(quantity)
def total_quantity(lines):
"""Add up the quantity column of 'item,quantity' lines."""
total = 0
for line in lines[1:]: # the first line is the header
item, quantity = line.split(",")
total += int(quantity)
return total
The header is known to be first, so it is skipped because it is first. Testing its text would tie the code to one supplier’s column names.
Nothing here catches ValueError. A header is expected and handled; 'lots' in a quantity column is not, and the caller hears about it.
lines[1:] of a header-only file is empty, and so is lines[1:] of an empty list. The loop does not run and the total stays 0.
For real CSV files, use the csv module: csv.DictReader reads the header for you and gives each row as a dict keyed by column name, and it handles quoted commas, which split(",") does not.
- Read the column by its name from the header instead of assuming it is second.
- Rewrite it with csv.DictReader over the lines and compare what changes.
- Make the ValueError say which line number held the bad quantity.