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

Setting up your Python development environment in IPython - Daniel Kronovet

Setting up your Python development environment in IPython - Daniel Kronovet

A walkthrough of the process of creating a good development workflow in Python (with a focus on IPython). This includes organizing the files in your project (and setting up relative imports through packages and modules), writing tests with Unittest, and debugging with pdb. This tutorial will also include a section on the extra features of IPython.

PyGotham 2014

August 17, 2014
Tweet

More Decks by PyGotham 2014

Other Decks in Programming

Transcript

  1. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Four Life Changing Lessons

    Choosing an Interpreter Understanding Imports Knowing How to Test Learning the Debugger
  2. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Four Life Changing Lessons

    Choosing an Interpreter__ Understanding Imports Knowing How to Test Learning the Debugger
  3. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 The Answer $ pip

    install ipython installing ... $ ipython In [1]: _
  4. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Things You Want Magic

    Commands History Tab Completion Introspection
  5. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Magic Commands %run (run

    any python file) %debug (teleport into an error) %prun (profile your code) %timeit (time your code)
  6. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 History In [1]: 2

    + 2 Out [1]: 4 In [2]: 1 + _ Out [2]: 5 In [3]: Out[2] * 2 Out [3]: 10
  7. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Tab Completion In [1]:

    lst = [ ] In [2]: lst.tab lst.append lst.count lst.extend lst.index lst.insert lst.pop lst.remove lst.reverse lst.sort
  8. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Introspection In [1]: dct

    = { } In [2]: dct? Type: dict String form: {} Length: 0 Docstring: dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's...
  9. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Example From My Life

    Flask on top of Flask-MongoAlchemy on top of MongoAlchemy on top of PyMongo on top of MongoDB
  10. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Four Life Changing Lessons

    Choosing an Interpreter Understanding Imports__ Knowing How to Test Learning the Debugger
  11. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Import Syntax import module

    from module import Class import module.function as fx from module import * (BAD)
  12. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 __init__.py mypkg/ __init__.py module_a.py

    module_b.py ____________________________ __init__.py: import module_a
  13. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 __init__.py In [1]: import

    mypkg In [2]: mypkg.module_a.foo( ) Out [2]: 'bar'
  14. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Explicit Imports In [3]:

    mypkg.module_b.baz( ) Out [3]: AttributeError: 'module' object has no attribute 'module_b'
  15. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Explicit Imports In [4]:

    import mypkg.module_b In [5]: mypkg.module_b.baz( ) Out [5]: 'Go Bears!'
  16. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Your Interpreter’s POV mypkg/

    mypkg/ __init__.py module_a.py module_b.py tests/ test_module_a.py test_module_b.py
  17. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Your Interpreter’s POV mypkg/

    $ ipython mypkg/ __init__.py module_a.py module_b.py tests/ test_module_a.py test_module_b.py
  18. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Local Import In [1]:

    import mypkg In [2]: mypkg Out [2]: <module 'mypkg' from 'mypkg/__init__.pyc'>
  19. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Your Interpreter’s POV mypkg/

    mypkg/ $ ipython __init__.py module_a.py module_b.py tests/ test_module_a.py test_module_b.py
  20. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Disaster Strikes! In [1]:

    import mypkg Out [1]: ImportError: No module named mypkg
  21. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Seems Okay... In [2]:

    import module_a In [3]: module_a Out [3]: <module 'module_a' from 'module_a.pyc'>
  22. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Your Interpreter’s POV mypkg/

    mypkg/ $ ipython __init__.py module_a.py module_b.py tests/ test_module_a.py test_module_b.py
  23. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Great Success! In [1]:

    import mypkg In [2]: mypkg Out [2]: <module 'mypkg' from '/path/ to/mypkg/mypkg/__init__.py'>
  24. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Four Life Changing Lessons

    Understanding Imports Choosing an Interpreter Knowing How to Test__ Learning the Debugger
  25. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 A Test File tests/test_module_a.py:

    import unittest class TestCls(unittest.TestCase): def test_one(self): assert 1+1 == 2
  26. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Using A Framework $

    pip install pytest installing … $ py.test_
  27. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Using A Framework $

    pip install pytest installing … $ py.test ======= test session starts ======= collected 1 item
  28. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Using A Framework $

    pip install pytest installing … $ py.test ======= test session starts ======= collected 1 item tests/test_module_a.py .
  29. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Lots of Options $

    py.test tests/test_module_a.py and / or $ py.test -x (fail fast) and / or $ py.test --pdb (auto debug) and / or $ py.test -s (if using ipdb)
  30. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Two Schools of Thought

    Micro-testing (unit tests) (document specific behavior) Macro-testing (integration tests) (document general behavior)
  31. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Pick Two of Three

    Rigorous DRY Fast Slow, excessive setup functions.
  32. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Pick Two of Three

    Rigorous DRY Fast Tests include boilerplate setup code.
  33. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Pick Two of Three

    Rigorous DRY Fast Risk of introducing unexpected data.
  34. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Four Life Changing Lessons

    Understanding Imports Choosing an Interpreter Knowing How to Test Learning the Debugger__
  35. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Two Points of Entry

    import pdb; pdb.set_trace( ) (& run code as usual) or $ py.test --pdb tests/ test_module_a.py (automatic break at exception)
  36. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Essential Commands u -

    go up one stack level d - go down one stack level n - go to the next line s - step into the function call l - show the surrounding lines c - continue to next breakpoint b # - set a new breakpoint at line # q - quit the debugger
  37. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Putting It All Together

    mypkg/module_b.py: def square(x): ans = x ** x return ans
  38. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Putting It All Together

    tests/test_module_b.py: import unittest from mypkg.module_b import square class TestMath(unittest.TestCase): def test_square(self): result = square(10) assert result == 100
  39. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Running the test... $

    py.test ======= test session starts ======= collected 2 items tests/test_module_a.py .
  40. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Running the test... $

    py.test ======= test session starts ======= collected 2 items tests/test_module_a.py . tests/test_module_b.py F E AssertionError: assert 10000000000 == 100
  41. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Let’s toss in a

    binding. tests/test_module_b.py: import unittest from mypkg.module_b import square class TestMath(unittest.TestCase): def test_square(self): import pdb; pdb.set_trace( ) result = square(10) assert result == 100
  42. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Start from the top.

    $ py.test tests/test_module_b.py Some stuff... -> result = square(10) (Pdb) _
  43. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Step by step... $

    py.test tests/test_module_b.py Some stuff... -> result = square(10) (Pdb) s_ (let’s step into the function)
  44. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Step by step... --Call--

    > .../mypkg/module_b.py(1)square( ) -> def square(x): (Pdb) _
  45. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Step by step... --Call--

    > .../mypkg/module_b.py(1)square( ) -> def square(x): (Pdb) l_ (let’s see where we are)
  46. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Step by step... --Call--

    > .../mypkg/module_b.py(1)square( ) -> def square(x): (Pdb) l 1 -> def square(x): 2 ans = x ** x 3 return ans (Pdb) _
  47. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Step by step... --Call--

    > .../mypkg/module_b.py(1)square( ) -> def square(x): (Pdb) l 1 -> def square(x): 2 ans = x ** x 3 return ans (Pdb) n_ (let’s move to the next line)
  48. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Where does x go

    wrong? -> ans = x ** x (Pdb) ans_ (let’s check the value)
  49. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Where does x go

    wrong? -> ans = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) _
  50. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Let’s try science. ->

    ans = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) n_
  51. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Let’s try science. ->

    ans = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) n -> return ans (Pdb) _
  52. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Trying to isolate the

    problem... -> ans = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) n -> return ans (Pdb) ans_ (let’s check again)
  53. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Trying to isolate the

    problem... -> ans = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) n -> return ans (Pdb) ans 10000000000 (Pdb) _
  54. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Found it. -> ans

    = x ** x (Pdb) ans * NameError: name 'ans' is not defined (Pdb) n -> return ans (Pdb) ans 10000000000 (bingo) (Pdb) _
  55. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Fingers crossed... $ py.test

    ======= test session starts ======= collected 2 items tests/test_module_a.py .
  56. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 World Peace. $ py.test

    ======= test session starts ======= collected 2 items tests/test_module_a.py . tests/test_module_b.py . ==== 2 passed in 0.16 seconds ====
  57. Daniel Kronovet ~ @kronosapiens ~ PyGotham2014 Thanks! Daniel Kronovet [email protected]

    @kronosapiens kronosapiens.github.io github.com/kronosapiens