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.

SF Python
October 12th 2016

Matt Robenolt

October 12, 2016
Tweet

More Decks by Matt Robenolt

Other Decks in Programming

Transcript

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

    View Slide

  2. Jams Cunningham
    hello

    View Slide

  3. Core contributor

    View Slide

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


    View Slide

  5. Damn Stebe, it works for me.
    gtfo my inbox.


    — Josh

    View Slide

  6. View Slide

  7. But first,
    some broken software!

    View Slide

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

    View Slide

  9. #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

    View Slide

  10. #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

    View Slide

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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. 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

    View Slide

  15. 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.

    View Slide

  16. 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

    View Slide

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

    View Slide

  18. 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'

    View Slide

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

    View Slide

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

    View Slide

  21. Exceptions
    Errors
    vs

    View Slide

  22. Errors

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. 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'

    View Slide

  27. 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?

    View Slide

  28. 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?

    View Slide

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

    View Slide

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

    View Slide

  31. 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'), 0x106810ea8>)

    View Slide

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

    View Slide

  33. 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'

    View Slide

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

    View Slide

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

    View Slide

  36. 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'), 0x106810ea8>)

    View Slide

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

    View Slide

  38. 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'

    View Slide

  39. import sys
    print(sys.exc_info())

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  46. $ python main.py 2> errors.log

    View Slide

  47. View Slide

  48. $ cat errors.log

    View Slide

  49. $ 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

    View Slide

  50. $ 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'

    View Slide

  51. $ 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'

    View Slide

  52. 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'

    View Slide

  53. Damn Stebe, that
    variable should be
    right. You must
    have messed it up.


    — Darrell

    View Slide

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

    View Slide

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

    View Slide

  56. 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'})

    View Slide

  57. 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'})

    View Slide

  58. 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)

    View Slide

  59. 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)

    View Slide

  60. 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}

    View Slide

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

    View Slide

  62. 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}}

    View Slide

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


    View Slide

  64. Sentry.
    Gotta get all dat context.

    View Slide

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

    View Slide