Slide 1

Slide 1 text

Everything is broken, and I don’t know why. Python edition SF Python October 12th 2016 Matt Robenolt

Slide 2

Slide 2 text

Jams Cunningham hello

Slide 3

Slide 3 text

Core contributor

Slide 4

Slide 4 text

If an exception happens in production, and nobody sees the logs, did it really happen? — Taylor Swift “ ”

Slide 5

Slide 5 text

Damn Stebe, it works for me. gtfo my inbox. “ ” — Josh

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

But first, some broken software!

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

#include 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

Slide 10

Slide 10 text

#include int main () { FILE *fp; char buf[100]; fp = fopen("foo.txt", “r"); if (fp != NULL) { fgets(buf, 100, fp); fclose(fp); } } Errors in: C

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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.

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

fp = open('foo.txt', 'r') buf = fp.read(100) fp.close() Errors in: Python

Slide 18

Slide 18 text

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 fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Exceptions Errors vs

Slide 22

Slide 22 text

Errors

Slide 23

Slide 23 text

Errors Non-fatal, multiple may exist within a call stack at the same time, generally returned as a value.

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Traceback (most recent call last): File "main.py", line 1, in 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?

Slide 29

Slide 29 text

fp = open('foo.txt', 'r') buf = fp.read(100) fp.close()

Slide 30

Slide 30 text

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()

Slide 31

Slide 31 text

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() (, IOError(2, 'No such file or directory'), )

Slide 32

Slide 32 text

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()

Slide 33

Slide 33 text

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 fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'

Slide 34

Slide 34 text

fp = open('foo.txt', 'r') buf = fp.read(100) fp.close()

Slide 35

Slide 35 text

try: fp = open('foo.txt', 'r') except IOError: import sys print(sys.exc_info()) else: buf = fp.read(100) fp.close()

Slide 36

Slide 36 text

try: fp = open('foo.txt', 'r') except IOError: import sys print(sys.exc_info()) else: buf = fp.read(100) fp.close() (, IOError(2, 'No such file or directory'), )

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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 fp = open('foo.txt', 'r') IOError: [Errno 2] No such file or directory: 'foo.txt'

Slide 39

Slide 39 text

import sys print(sys.exc_info())

Slide 40

Slide 40 text

import sys print(sys.exc_info()) (None, None, None)

Slide 41

Slide 41 text

import sys try: raise Exception() except Exception: pass print(sys.exc_info())

Slide 42

Slide 42 text

import sys try: raise Exception() except Exception: pass print(sys.exc_info()) (None, None, None)

Slide 43

Slide 43 text

try: raise Exception() except Exception: import sys print(sys.exc_info())

Slide 44

Slide 44 text

try: raise Exception() except Exception: import sys print(sys.exc_info()) (, Exception(), )

Slide 45

Slide 45 text

try: raise Exception() except Exception: import traceback, sys traceback.print_exc(file=sys.stderr)

Slide 46

Slide 46 text

$ python main.py 2> errors.log

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

$ cat errors.log

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Damn Stebe, that variable should be right. You must have messed it up. “ ” — Darrell

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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 things[key] KeyError: 'thing' ({'things': {},'key': 'thing'}, {'things': {}, 'key': 'thing'})

Slide 57

Slide 57 text

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 things[key] KeyError: 'thing' ({'things': {},'key': 'thing'}, {'things': {}, 'key': 'thing'})

Slide 58

Slide 58 text

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)

Slide 59

Slide 59 text

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)

Slide 60

Slide 60 text

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}

Slide 61

Slide 61 text

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()

Slide 62

Slide 62 text

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': ‘', 'line': 31, 'locals': {'things': [0, 1, 2]}} {'function': 'get_random_thing', 'line': 7, 'locals': {'n': 4}} {'function': 'get_thing', 'line': 11, 'locals': {'index': 4}}

Slide 63

Slide 63 text

Hot damn Stebe, thanks for the information. Lemme fix that bug for you right away. “ ”

Slide 64

Slide 64 text

Sentry. Gotta get all dat context.

Slide 65

Slide 65 text

Questions? I may or may not have answers. @mattrobenolt github.com/mattrobenolt sentry.io github.com/getsentry/sentry