Debugging
During the lecture, you learned some strategies to debug a program. Time to apply them! You’ll keep a logbook, like they did for “First actual case of bug being found”.
We want to find the total the kinetic energy of the a group of bodies, from a file that details their mass and speed.
You might need to review the equation and unit convertions formulas.
Instructions
- Create a new branch (called
exercise-debugging). - Create a new folder where you put:
- Try to fix the program. Describe your approach on the
debugging-logbook.txtfile.- Remember the learnings from error messages and logging.
- Try to solve one problem at a time, commit the fix and move to the next.
- Open a Merge request in your repository titled “Exercise: Debugging Kinectic Energy”.
- Assign it yourself.
- Add the lecturer (Manuel Reis) as reviewer.
Want help? How to run the script
It shows the usage message if you don’t provide a filename. You might need to mark it as executable chmod u+x kinectic.py
python kinetic.pyCRITICAL:__main__:Usage: kinetic.py filename [--debug]
There is already some debug logging but you might need to add more or modify them.
python kinetic.py bodies.txt --debugDEBUG:__main__:Parsing 1000g
DEBUG:__main__:Parsed value '1000' and unit 'fee/s'
ERROR:__main__:Failed processing 1000g@10km/h
DEBUG:__main__:Parsing 2kg
DEBUG:__main__:Parsed value '2k' and unit 'fee/s'
ERROR:__main__:Failed processing 2kg@3m/s
DEBUG:__main__:Parsing 500g
DEBUG:__main__:Parsed value '500' and unit 'fee/s'
ERROR:__main__:Failed processing 500g@5Km/h
DEBUG:__main__:Parsing 5kg
DEBUG:__main__:Parsed value '5k' and unit 'fee/s'
ERROR:__main__:Failed processing 5kg@1feet/s
DEBUG:__main__:Parsing 𝟙𝟘𝟘𝟘g
DEBUG:__main__:Parsed value '𝟙𝟘𝟘𝟘' and unit 'fee/s'
ERROR:__main__:Failed processing 𝟙𝟘𝟘𝟘g@1km/h
DEBUG:__main__:Parsing 730 g
DEBUG:__main__:Parsed value '730' and unit 'fee/s'
ERROR:__main__:Failed processing 730 g @ 1.1 m/s
DEBUG:__main__:Parsing 1Kg
DEBUG:__main__:Parsed value '1k' and unit 'fee/s'
ERROR:__main__:Failed processing 1Kg @2m /s
Total energy: 0 J
There are at least 4 bugs in the code. The correct result for the input file is ≈ 16.05 J.
Footnotes
Here is the input file!
↩︎bodies.txt
1000g@10km/h 2kg@3m/s 500g@5Km/h 5kg@1feet/s 𝟙𝟘𝟘𝟘g@1km/h 730g @ 1.1 m/s 1Kg@2m /sHere is the buggy script that computes the sum of Kinetic energies from the bodies present in the input file. The input file should contain one line per body, and it should be of the from
<mass><unit>@<velocity><unit>. Note that whitespaces (" ","\t") are ignored and letter case is insensitive.↩︎kinetic.py
#!/usr/bin/env python import logging from sys import argv, exit logging.basicConfig() logger = logging.getLogger(__name__) def kinetic_energy(mass, velocity): """Kinetic Energy formula 1/2 * m * v ** 2""" return 0.5 * mass * velocity def total_energy(samples): total = 0 for mass, velocity in samples: ke = kinetic_energy(mass, velocity) logger.debug("1/2 * %s * %s ** 2 = %s", mass, velocity, ke) total += ke return total def parse_units(input_str: str) -> tuple[int, str]: """Splits units from the end of string, returns truncated input and parsed unit""" logger.debug("Parsing %s", input_str) # Ignoring case and removing whitespaces input_str = input_str.lower().replace(" ", "").replace("\t", "") value, unit = None, None for unit in ( "kg", "g", "km/s", "m/s", "km/h", "fee/s", ): if input_str.endswith(unit): value = input_str.replace(unit, "") # We're done, we found the unit logger.debug("Parsed value '%s' and unit '%s'", value, unit) return float(value), unit def convert_units(value, unit): if unit == "g": return value / 1000 elif unit == "kg": return value elif unit == "km/h": return value * 0.2 # Aproximation elif unit == "m/s": return value elif unit == "feet/s": return value * 0.3048 raise ValueError("Unsupported unit type: %s", unit) def read_data(file_path): samples = [] with open(file_path, "r") as f: for line in f: try: parts = line.strip().split("@") mass_value, unit = parse_units(parts[0]) mass = convert_units(mass_value, unit) logger.info("Convertion Mass %s %s to %s Kg", mass_value, unit, mass) velocity_value, unit = parse_units(parts[1]) velocity = convert_units(velocity_value, unit) logger.info( "Convertion Velocity %s %s to %s m/s", velocity_value, unit, mass ) samples.append((mass, velocity)) except Exception: logger.error("Failed processing %s ", line.strip()) continue return samples if __name__ == "__main__": if len(argv) < 2: logger.critical("Usage: %s filename [--debug]", argv[0]) exit(1) if "--debug" in argv[1:]: logger.setLevel(logging.DEBUG) filename = argv[1] data = read_data(filename) print("Total energy:", total_energy(data), "J")