92
The Hidden Power of the Python Runtime Elizaveta Shashkova EuroPython 2020 Online

The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

The Hidden Power of the Python Runtime

Elizaveta Shashkova EuroPython 2020

Online

Page 2: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

About Me

• Software Developer at JetBrains, PyCharm IDE

• St Petersburg, Russia

• @lisa_shashkova

• Discord: #talk-python-runtime

!2

Page 3: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova!3

The hidden power?

Page 4: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova!4

The hidden power?

You already use it every day

Page 5: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Test Frameworks

• unittest

• pytest

!5

Page 6: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

AssertionError

• unittest

!6

Traceback (most recent call last): File “/file.py”, line 8, in test_value assert a == 2, "Wrong value!" AssertionError: Wrong value!

Page 7: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

AssertionError

• unittest

• pytest

!7

Traceback (most recent call last): File “/file.py”, line 8, in test_value assert a == 2, "Wrong value!" AssertionError: Wrong value!

E AssertionError: Wrong value! E assert 1 == 2

Page 8: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Contents

• Python Runtime

• Getting Runtime Information

• Development Tools

!8

Page 9: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Contents

• Python Runtime

• Getting Runtime Information

• Development Tools

!9

Page 10: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Objects

• Created explicitly

• variables, functions, classes, modules

!10

Page 11: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Objects

• Created explicitly

• variables, functions, classes, modules

• Created implicitly

• stack frame, code object

!11

Page 12: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

• Represents a program scope

• Information about execution state:

• Corresponding code object

• Local and global variables

• Other data

!12

Page 13: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

!13

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

module

bar()

1 2 3 4 5 6 7 8 9 10 11

Page 14: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

!14

module

bar()

foo()

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

1 2 3 4 5 6 7 8 9 10 11

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

Page 15: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

!15

module

bar()

foo()

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

1 2 3 4 5 6 7 8 9 10 11

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

Page 16: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

!16

module

bar()

foo()

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

1 2 3 4 5 6 7 8 9 10 11

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

Page 17: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Stack Frame

!17

module

bar()

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

1 2 3 4 5 6 7 8 9 10 11

def foo(n): n = n - 1 return n

def bar(k): res = foo(k) return res * 2

print(bar(1))

Page 18: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Power

• Available out of the box

!18

module

bar()

Page 19: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Power

• Available out of the box

• Stack frame objects access

!19

module

bar()

Page 20: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Contents

• Python Runtime

• Getting Runtime Information

• Development Tools

!20

Page 21: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Stack Frame

•sys._getframe([depth])

•depth - number of calls below the top

•0 - current frame

!21

Page 22: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object

!22

Page 23: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object: Variables

!23

• Local variables

• frame.f_locals

Page 24: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object: Variables

!24

• Local variables

• frame.f_locals

• Global variables

• frame.f_globals

Page 25: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object: Variables

!25

• Local variables

• frame.f_locals

• Global variables

• frame.f_globals

• locals() & globals()

Page 26: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!26

•frame.f_code - frame’s attribute

Page 27: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!27

• Represents a chunk of executable code

Page 28: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!28

• Represents a chunk of executable code

>>> c = compile('a + b', 'a.py', 'eval')

<code object <module> at 0x104f8fc90, file "a.py", line 1>

Page 29: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!29

• Represents a chunk of executable code

>>> c = compile('a + b', 'a.py', 'eval')

<code object <module> at 0x104f8fc90, file "a.py", line 1>

>>> eval(c, {'a': 1, 'b': 2})

3

Page 30: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!30

•code.co_filename - filename where it was created

•code.co_name - name of function or module

•code.co_varnames - names of variables

Page 31: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Object

!31

•code.co_filename - filename where it was created

•code.co_name - name of function or module

•code.co_varnames - names of variables

•code.co_code - compiled bytecode,

disassemble with dis.dis()

Page 32: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object

!32

•frame.f_lineno - current line number

•frame.f_trace - tracing function

•frame.f_back - previous frame

Page 33: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Previous Frame

!33

module

bar()

foo()

Page 34: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Previous Frame

!34

Traceback (most recent call last): File "file.py", line 12, in <module> print(bar(1)) File "file.py", line 8, in bar res = foo(k) File "file.py", line 2, in foo raise ValueError("Wrong value!") ValueError: Wrong value!

module

bar()

foo()

Page 35: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object

!35

• inspect module

Page 36: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Object

!36

• inspect module

• Handle frame variable carefully!

def handle_stackframe_without_leak(): frame = inspect.currentframe() try: # do something with the frame finally: del frame

Page 37: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Contents

• Python Runtime

• Getting Runtime Information

• Development Tools

!37

Page 38: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Contents

• Python Runtime

• Getting Runtime Information

• Development Tools

!38

Page 39: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

!39

Page 40: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Exception Object

• tb = e.__traceback__ - traceback object

• tb.tb_frame - frame object

!40

Page 41: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

AssertionError Variables

!41

def vars_in_assert(e): tb = e.__traceback__ frame = tb.tb_frame code = frame.f_code line = tb.tb_lineno - code.co_firstlineno + 1 source = inspect.getsource(code)

Page 42: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

AssertionError Variables

!42

def get_vars_names(source, line): # get variables names with `ast` module

def vars_in_assert(e): tb = e.__traceback__ frame = tb.tb_frame code = frame.f_code line = tb.tb_lineno - code.co_firstlineno + 1 source = inspect.getsource(code) for name in get_vars_names(source, line): pass

Page 43: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

AssertionError Variables

!43

def get_vars_names(source, line): # get variables names with `ast` module

def vars_in_assert(e): tb = e.__traceback__ frame = tb.tb_frame code = frame.f_code line = tb.tb_lineno - code.co_firstlineno + 1 source = inspect.getsource(code) for name in get_vars_names(source, line): if name in frame.f_locals: var = frame.f_locals[name] print(f"{name} = {var}")

Page 44: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Usage

!44

>>> try: assert a + b < 1 except AssertionError as e: vars_in_assert(e)

Page 45: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Usage

!45

>>> try: assert a + b < 1 except AssertionError as e: vars_in_assert(e)

File “/file.py", line 10, in foo assert a + b < 1

Variables Values: a = 1 b = 2

Page 46: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

!46

Page 47: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

!47

Page 48: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Debugger

!48

Page 49: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Debugger

• Tracing function

• Frame evaluation function

!49

Page 50: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Tracing Function

• tracefunc(frame, event, arg)

• sys.settrace(tracefunc) - set to current frame

• Stored in a frame: frame.f_trace

• Debugger analyses events

!50

Page 51: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Frame Evaluation

• frame_eval(frame, exc) • Debugger inserts breakpoint’s code into code object

!51

Page 52: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

More About Debuggers

• PyCon US 2017

• “Debugging with Python 3.6: Better, Faster, Stronger”

!52

Page 53: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Access to Frame

• tracefunc(frame, event, arg)

• frame_eval(frame, exc)

!53

Page 54: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Debugger: Location

!54

• frame.f_code.co_filename and frame.f_lineno

Page 55: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Debugger: Variables

!55

• frame.f_locals

Page 56: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Debugger: Frames

!56

• frame.f_back

Page 57: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

!57

Page 58: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

• Code coverage

!58

Page 59: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Code Coverage

• Shows which lines were executed

!59

Page 60: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

coverage.py

!60

• The most popular code coverage library

Page 61: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

coverage.py

!61

• tracefunc(frame, event, arg)

• frame.f_code.co_filename and frame.f_lineno

Page 62: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

• Code coverage

!62

Page 63: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

• Code coverage

• Runtime typing tools

!63

Page 64: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!64

Page 65: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!65

Page 66: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!66

Page 67: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!67

Page 68: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!68

Page 69: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Acces To Frame

• PyAnnotate, MonkeyType:

• sys.setprofile(profilefunc)

• profilefunc(frame, event, arg)

!69

Page 70: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Acces To Frame

• “Collect Runtime information” in PyCharm

• Integrated with Debugger

• Access to a frame object

!70

Page 71: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Collecting Types

!71

def arg_names(co): nargs = co.co_argcount names = co.co_varnames return list(names[:nargs])

names = arg_names(frame.f_code)

Page 72: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Collecting Types

!72

def arg_names(co): nargs = co.co_argcount names = co.co_varnames return list(names[:nargs])

names = arg_names(frame.f_code) locs = frame.f_locals objects = [locs[n] for n in names]

Page 73: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Typing Tools

• PyAnnotate by Dropbox

• MonkeyType by Instagram

• “Collect Runtime information” in PyCharm

!73

Page 74: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

• Code coverage

• Runtime typing tools

• ?

!74

Page 75: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Concurrent Execution

• Threads

• Async Tasks

!75

Page 76: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Python Threads

!76

import threading

def fun(): print("Hello!")

t = threading.Thread(target=fun) t.start() t.join()

Page 77: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Synchronisation

• Lock - fundamental synchronisation object

!77

lock = threading.Lock()

lock.acquire() # only one thread here lock.release()

with lock: # equivalent

Page 78: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Deadlock

• Waiting for resources which can’t be released

!78

Page 79: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Deadlock

!79

def run1(): with lock1: with lock2: # do sth

def run2(): with lock2: with lock1: # do sth else

Thread(target=run1).start() Thread(target=run2).start()

Page 80: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Deadlock

• Waiting for resources which can’t be released

• Hard to detect in big projects

!80

Page 81: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Thread States

•sys._getframe() - frame object for current thread

•sys._current_frames() - topmost stack frame for each thread

!81

Page 82: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Thread Handler

• Print tracebacks for threads with interval

• Help to find deadlock location

!82

Page 83: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Fault Handler

•faulthandler.dump_traceback(file)

•Dumps the tracebacks of all threads info file

• Implemented natively

!83

Page 84: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Concurrent Execution

• Threads

• Async Tasks

!84

Page 85: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Async Locks

!85

alock = asyncio.Lock()

alock.acquire() # only one task here alock.release()

async with alock: # equivalent

Page 86: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Async Fault Handler

•asyncio.all_tasks(loop) - all the running tasks

•Task.get_stack() - list of stack frames for this Task

!86

Page 87: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Async Fault Handler

• In a separate thread:

!87

def dump_traceback_later(timeout, loop): while True: sleep(timeout) dump_traceback(loop, timeout)

Page 88: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Async Fault Handler

• In a separate thread:

!88

def dump_traceback(loop): for task in asyncio.all_tasks(loop): task.print_stack()

def dump_traceback_later(timeout, loop): while True: sleep(timeout) dump_traceback(loop, timeout)

Page 89: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Development Tools

• AssertionError in pytest

• Debugger

• Code coverage

• Runtime typing tools

• (Async) Fault Handler

!89

Page 90: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

The Hidden Power of Runtime

• Python Runtime is very powerful

• Easy access to stack frame and code objects

• Development Tools:

• pytest, Debugger, Code Coverage, Typing Information, Fault Handler

!90

Page 91: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Inspiration

• Use existing Runtime Development Tools (more often)

• Create something new!

!91

Page 92: The Hidden Power of the Python Runtime · 2020. 7. 24. · @lisa_shashkova About Me •Software Developer at JetBrains, PyCharm IDE •St Petersburg, Russia • @lisa_shashkova •Discord:

@lisa_shashkova

Links

• https://github.com/Elizaveta239/PyRuntimeTricks

• https://elizaveta239.github.io/the-hidden-power-part1/

[email protected]

• Discord: #talk-python-runtime

!92