Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Everything is broken, and I don't know why. Python edition.

Everything is broken, and I don't know why. Python edition.

PyOhio
July 30th 2017

Matt Robenolt

July 30, 2017
Tweet

More Decks by Matt Robenolt

Other Decks in Technology

Transcript

  1. If an exception happens in production, and nobody sees the

    logs, did it really happen? — Taylor Swift “ ”
  2. #include <stdio.h> int main () { FILE *fp; char buf[100];

    fp = fopen("foo.txt", "r"); fgets(buf, 100, fp); fclose(fp); } Errors in: C
  3. #include <stdio.h> int main () { FILE *fp; char buf[100];

    fp = fopen("foo.txt", "r"); fgets(buf, 100, fp); fclose(fp); } Errors in: C [1] 53482 segmentation fault ./a.out
  4. #include <stdio.h> int main () { FILE *fp; char buf[100];

    fp = fopen("foo.txt", “r"); if (fp != NULL) { fgets(buf, 100, fp); fclose(fp); } } Errors in: C
  5. package main import "os" func main() { buf := make([]byte,

    100) fp, _ := os.Open("foo.txt") fp.Read(buf) fp.Close() } Errors in: Go
  6. package main import "os" func main() { buf := make([]byte,

    100) fp, _ := os.Open("foo.txt") fp.Read(buf) fp.Close() } Errors in: Go jk nothing happens
  7. package main import "os" func main() { buf := make([]byte,

    100) fp, err := os.Open(“foo.txt") if err != nil { return } fp.Read(buf) fp.Close() } Errors in: Go
  8. use std::fs::File; use std::io::Read; fn main() { let mut fp

    = File::open("foo.txt").unwrap(); let mut buf = [0; 100]; fp.read_exact(&mut buf); drop(fp); } Errors in: Rust
  9. use std::fs::File; use std::io::Read; fn main() { let mut fp

    = File::open("foo.txt").unwrap(); let mut buf = [0; 100]; fp.read_exact(&mut buf); drop(fp); } Errors in: Rust thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 2, message: "No such file or directory" } }', ../src/ libcore/result.rs:788 note: Run with `RUST_BACKTRACE=1` for a backtrace.
  10. use std::fs::File; use std::io::Read; fn main() { match File::open("foo.txt") {

    Ok(mut fp) => { let mut buf = [0; 100]; fp.read_exact(&mut buf); drop(fp); }, Err(_) => { // }, } } Errors in: Rust
  11. fp = open('foo.txt', 'r') buf = fp.read(100) fp.close() Errors in:

    Python Traceback (most recent call last): File "main.py", line 1, in <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'
  12. try: fp = open('foo.txt', 'r') except IOError: pass else: buf

    = fp.read(100) fp.close() Errors in: Python
  13. try: fp = open('foo.txt', 'r') except IOError: pass else: buf

    = fp.read(100) fp.close() Errors in: Python Exceptions
  14. Errors Non-fatal, multiple may exist within a call stack at

    the same time, generally returned as a value.
  15. Exceptions Fatal, must be handled, only one exists within a

    call stack, raised to abort current execution.
  16. Exceptions Fatal, must be handled, only one exists within a

    call stack, raised to abort current execution.
  17. Traceback (most recent call last): File "main.py", line 1, in

    <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'
  18. Traceback (most recent call last): File "main.py", line 1, in

    <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt' So what do we do with this thing?
  19. Traceback (most recent call last): File "main.py", line 1, in

    <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt' So what do we do with this thing? …and where does it come from?
  20. import sys def excepthook(type, value, tb): print(type, value, tb) sys.excepthook

    = excepthook fp = open('foo.txt', 'r') buf = fp.read(100) fp.close()
  21. import sys def excepthook(type, value, tb): print(type, value, tb) sys.excepthook

    = excepthook fp = open('foo.txt', 'r') buf = fp.read(100) fp.close() (<type 'exceptions.IOError'>, IOError(2, 'No such file or directory'), <traceback object at 0x106810ea8>)
  22. import sys def excepthook(type, value, tb): import traceback traceback.print_exception(type, value,

    tb) sys.excepthook = excepthook fp = open('foo.txt', 'r') buf = fp.read(100) fp.close()
  23. import sys def excepthook(type, value, tb): import traceback traceback.print_exception(type, value,

    tb) sys.excepthook = excepthook fp = open('foo.txt', 'r') buf = fp.read(100) fp.close() Traceback (most recent call last): File "main.py", line 9, in <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'
  24. try: fp = open('foo.txt', 'r') except IOError: import sys print(sys.exc_info())

    else: buf = fp.read(100) fp.close() (<type 'exceptions.IOError'>, IOError(2, 'No such file or directory'), <traceback object at 0x106810ea8>)
  25. try: fp = open('foo.txt', 'r') except IOError: import sys, traceback

    traceback.print_exception(*sys.exc_info()) else: buf = fp.read(100) fp.close()
  26. try: fp = open('foo.txt', ‘r') except IOError: import traceback traceback.print_exc()

    else: buf = fp.read(100) fp.close() Traceback (most recent call last): File "main.py", line 2, in <module> fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'
  27. $ cat errors.log raise Exception() Exception Traceback (most recent call

    last): File "main.py", line 3, in <module> raise Exception() Exception Traceback (most recent call last): File "main.py", line 3, in <module> raise Exception() Exception Traceback (most recent call last): File "main.py", line 3, in <module> raise Exception() Exception Traceback (most recent call last): File "main.py", line 3, in <module>
  28. $ cat errors.log Traceback (most recent call last): File "main.py",

    line 4, in <module> my_thing = things[key] KeyError: 'thing1' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing2' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing3' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing4'
  29. $ cat errors.log Traceback (most recent call last): File "main.py",

    line 4, in <module> my_thing = things[key] KeyError: 'thing1' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing2' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing3' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing4'
  30. Traceback (most recent call last): File "main.py", line 4, in

    <module> my_thing = things[key] KeyError: 'thing1' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing2' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing3' Traceback (most recent call last): File "main.py", line 4, in <module> my_thing = things[key] KeyError: 'thing4'
  31. things = {} key = sys.argv[1] try: my_thing = things[key]

    except KeyError: import traceback traceback.print_exc() print(globals(), locals())
  32. things = {} key = sys.argv[1] try: my_thing = things[key]

    except KeyError: import traceback traceback.print_exc() print(globals(), locals())
  33. things = {} key = sys.argv[1] try: my_thing = things[key]

    except KeyError: import traceback traceback.print_exc() print(globals(), locals()) Traceback (most recent call last): File "main.py", line 5, in <module> things[key] KeyError: 'thing' ({'things': {},'key': 'thing'}, {'things': {}, 'key': 'thing'})
  34. things = {} key = sys.argv[1] try: my_thing = things[key]

    except KeyError: import traceback traceback.print_exc() print(globals(), locals()) Traceback (most recent call last): File "main.py", line 5, in <module> things[key] KeyError: 'thing' ({'things': {},'key': 'thing'}, {'things': {}, 'key': 'thing'})
  35. things = {} key = sys.argv[1] try: my_thing = things[key]

    except KeyError: import traceback, json, sys json.dump({ 'exc': traceback.format_exc(), 'globals': globals(), 'locals': locals(), }, sys.stderr) Don’t actually do this, use: https://github.com/hynek/structlog
  36. things = [0, 1, 2] def get_random_thing(n): return get_thing(randint(0, n))

    def get_thing(index): try: return things[index] except IndexError: print(locals()) get_random_thing(10)
  37. things = [0, 1, 2] def get_random_thing(n): return get_thing(randint(0, n))

    def get_thing(index): try: return things[index] except IndexError: print(locals()) get_random_thing(10) {'index': 8}
  38. def debug(): import sys tb = sys.exc_info()[2] idx = 0

    while tb: idx += 1 frame = tb.tb_frame code = frame.f_code print({ 'line': tb.tb_lineno, 'locals': frame.f_locals, 'function': code.co_name, }) tb = tb.tb_next try: get_random_thing(10) except Exception: debug()
  39. def debug(): import sys tb = sys.exc_info()[2] idx = 0

    while tb: idx += 1 frame = tb.tb_frame code = frame.f_code print({ 'line': tb.tb_lineno, 'locals': frame.f_locals, 'function': code.co_name, }) tb = tb.tb_next try: get_random_thing(10) except Exception: debug() {'function': ‘<module>', 'line': 31, 'locals': {'things': [0, 1, 2]}} {'function': 'get_random_thing', 'line': 7, 'locals': {'n': 4}} {'function': 'get_thing', 'line': 11, 'locals': {'index': 4}}
  40. def debug(): report = { 'context': { 'argv': sys.argv, 'environ':

    os.environ, 'uname': os.uname(), 'time': time.time(), }, 'frames': [], }
  41. _, e, tb = sys.exc_info() idx = 0 while tb:

    idx += 1 frame = tb.tb_frame code = frame.f_code report['frames'].append({ 'line': tb.tb_lineno, 'locals': frame.f_locals, 'function': code.co_name, 'filename': code.co_filename, 'context': linecache.getline( code.co_filename, tb.tb_lineno, ), }) tb = tb.tb_next