Fix this program. Make sure to keep the format "var: value". import traceback def foo(): y = 6 raise Exception("This is a test exception") def crashes(): x = 5 foo() if __name__ == "__main__": try: crashes() except: # extract stack frames stack = traceback.extract_stack() # print all locals in each stack frame for frame in stack: for k,v in frame.locals: print(k + ": " + v)
Fix this program. Make sure to keep the format "var: value". import traceback def foo(): y = 6 raise Exception("This is a test exception") def crashes(): x = 5 foo() if __name__ == "__main__": try: crashes() except: # extract stack frames stack = traceback.extract_stack() # print all locals in each stack frame for frame in stack: for k,v in frame.locals: print(k + ": " + v)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import traceback import sys # Import sys to access exception info def foo(): y = 6 z = [1, 2, 3] # Add another local for demonstration raise Exception("This is a test exception") def crashes(): x = 5 msg = "About to call foo" # Add another local foo() if __name__ == "__main__": try: crashes() except Exception: # Catch the specific exception type if known, or general Exception # Get the exception info (type, value, traceback object) exc_type, exc_value, exc_traceback = sys.exc_info() print("--- Traceback Locals ---") # The traceback object (exc_traceback) is a linked list. # We need to iterate through it to get the frames *at the time of the exception*. # traceback.extract_stack() gets the stack where it's *called*, not where the exception happened. tb = exc_traceback while tb is not None: # Get the actual frame object from the traceback object frame = tb.tb_frame # Get the dictionary of locals from the frame object locals_dict = frame.f_locals # Print function name for context print(f"\nLocals in function: {frame.f_code.co_name} (line {tb.tb_lineno})") if locals_dict: # Iterate through the locals dictionary for k, v in locals_dict.items(): # Use str(v) to handle non-string types and format correctly print(f"{k}: {str(v)}") else: print("(No locals in this frame)") # Move to the next frame up the stack tb = tb.tb_next print("\n--- End Traceback Locals ---") # Optional: print the standard traceback as well # print("\n--- Standard Traceback ---") # traceback.print_exception(exc_type, exc_value, exc_traceback) |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import traceback import sys # Import sys to access exception info def foo(): y = 6 z = [1, 2, 3] # Add another local for demonstration raise Exception("This is a test exception") def crashes(): x = 5 msg = "About to call foo" # Add another local foo() if __name__ == "__main__": try: crashes() except Exception: # Catch the specific exception type if known, or general Exception # Get the exception info (type, value, traceback object) exc_type, exc_value, exc_traceback = sys.exc_info() print("--- Traceback Locals ---") # The traceback object (exc_traceback) is a linked list. # We need to iterate through it to get the frames *at the time of the exception*. # traceback.extract_stack() gets the stack where it's *called*, not where the exception happened. tb = exc_traceback while tb is not None: # Get the actual frame object from the traceback object frame = tb.tb_frame # Get the dictionary of locals from the frame object locals_dict = frame.f_locals # Print function name for context print(f"\nLocals in function: {frame.f_code.co_name} (line {tb.tb_lineno})") if locals_dict: # Iterate through the locals dictionary for k, v in locals_dict.items(): # Use str(v) to handle non-string types and format correctly print(f"{k}: {str(v)}") else: print("(No locals in this frame)") # Move to the next frame up the stack tb = tb.tb_next print("\n--- End Traceback Locals ---") # Optional: print the standard traceback as well # print("\n--- Standard Traceback ---") # traceback.print_exception(exc_type, exc_value, exc_traceback) |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import traceback import sys # Import sys to access exception info def foo(): y = 6 z = [1, 2, 3] # Add another local for demonstration raise Exception("This is a test exception") def crashes(): x = 5 msg = "About to call foo" # Add another local foo() if __name__ == "__main__": try: crashes() except Exception: # Catch the specific exception type if known, or general Exception # Get the exception info (type, value, traceback object) exc_type, exc_value, exc_traceback = sys.exc_info() print("--- Traceback Locals ---") # The traceback object (exc_traceback) is a linked list. # We need to iterate through it to get the frames *at the time of the exception*. # traceback.extract_stack() gets the stack where it's *called*, not where the exception happened. tb = exc_traceback while tb is not None: # Get the actual frame object from the traceback object frame = tb.tb_frame # Get the dictionary of locals from the frame object locals_dict = frame.f_locals # Print function name for context print(f"\nLocals in function: {frame.f_code.co_name} (line {tb.tb_lineno})") if locals_dict: # Iterate through the locals dictionary for k, v in locals_dict.items(): # Use str(v) to handle non-string types and format correctly print(f"{k}: {str(v)}") else: print("(No locals in this frame)") # Move to the next frame up the stack tb = tb.tb_next print("\n--- End Traceback Locals ---") # Optional: print the standard traceback as well # print("\n--- Standard Traceback ---") # traceback.print_exception(exc_type, exc_value, exc_traceback) |
--- Traceback Locals ---
Locals in function: <module> (line 18)
__name__: __main__
Traceback (most recent call last):
File "/usr/src/app/main.py", line 18, in <module>
crashes()
File "/usr/src/app/main.py", line 13, in crashes
foo()
File "/usr/src/app/main.py", line 8, in foo
raise Exception("This is a test exception")
Exception: This is a test exception
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/src/app/main.py", line 39, in <module>
for k, v in locals_dict.items():
RuntimeError: dictionary changed size during iteration
Testing if the previous output contains the string y: 6
: False
Testing if the previous output contains the string x: 5
: False