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

Migrating from PHP to Python and Django

Migrating from PHP to Python and Django

Many programmers cut their teeth with PHP before getting interested in Python. However, while the languages seem similar at first, there are many new concepts to grasp and a rich ecosystem of tools to master. This isn't easy, but with the right advice, a strong PHP developer can become an excellent Python developer very quickly.

Based on the experience of migrating a development team from PHP to Python and Django, this talk will examine how to tackle this journey. While the fundamental languages differences will be touched upon, this talk will focus on more interesting topics such as common python gotchas, tips for grokking Django, awesome tools and applications from the community, and how to manage such a migration for a large team of developers.

David Winterbottom

March 02, 2012
Tweet

More Decks by David Winterbottom

Other Decks in Programming

Transcript

  1. Migrating from
    to
    and
    David Winterbottom
    @codeinthehole
    and

    View Slide

  2. View Slide

  3. •2010: In-house PHP framework
    •2012: Python, Django

    View Slide

  4. Why?
    •General purpose language
    •Elegant, readable
    •BDFL

    View Slide

  5. Today
    •Introduction to Python
    •Introduction to Django

    View Slide

  6. View Slide

  7. View Slide

  8. Zen of python

    View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. What’s
    http://www.davidshrigley.com/photo_htmpgs/lost_pidgeon.html

    View Slide

  13. Cruft
    •Significant whitespace
    •() ; not required
    •Readability counts!

    View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. Privacy
    •Nothing truly private
    •_name not in public API
    •__name mangled

    View Slide

  18. switch () {}

    View Slide

  19. View Slide

  20. View Slide

  21. OO
    •Type-hinting
    •Interfaces
    •Duck typing

    View Slide

  22. View Slide

  23. Don’t check type

    View Slide

  24. Don’t check type

    View Slide

  25. View Slide

  26. View Slide

  27. View Slide

  28. Server set-up
    • Easy: apache2, mod_php
    • Tricky: apache2, mod_wsgi, ...
    • ...but getting better:
    • Servers: gunicorn, uWSGI
    • Platforms: ep.io, gondor.io

    View Slide

  29. View Slide

  30. >>> dir()
    ['__builtins__', '__doc__', '__name__', '__package__']
    >>> dir(__builtins__)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning',
    'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
    'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
    'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
    'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
    'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_',
    '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin',
    'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
    'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file',
    'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
    'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max',
    'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range',
    'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
    'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
    built-ins

    View Slide

  31. >>> dir()
    ['__builtins__', '__doc__', '__name__', '__package__']
    >>> dir(__builtins__)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning',
    'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
    'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
    'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
    'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
    'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_',
    '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin',
    'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
    'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file',
    'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
    'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max',
    'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range',
    'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
    'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
    built-ins

    View Slide

  32. >>> dir()
    ['__builtins__', '__doc__', '__name__', '__package__']
    >>> dir(__builtins__)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning',
    'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
    'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
    'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
    'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
    'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_',
    '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin',
    'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
    'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file',
    'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
    'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max',
    'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range',
    'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
    'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
    built-ins

    View Slide

  33. View Slide

  34. TypeError
    >>> 'hello' + 100
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: cannot concatenate 'str' and 'int' objects
    >>>
    duck, dynamic, strong

    View Slide

  35. TypeError
    >>> 'hello' + 100
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: cannot concatenate 'str' and 'int' objects
    >>>
    duck, dynamic, strong

    View Slide

  36. TypeError
    >>> 'hello' + 100
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: cannot concatenate 'str' and 'int' objects
    >>>
    duck, dynamic, strong

    View Slide

  37. TypeError
    >>> 'hello' + 100
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: cannot concatenate 'str' and 'int' objects
    >>>
    duck, dynamic, strong

    View Slide

  38. Data-structures
    •PHP: array()
    •tuple(), dict(), set(), list(), , ...
    •... deque(), defaultdict() -
    collections

    View Slide

  39. Inheritance
    multiple inheritance

    View Slide

  40. Modules!
    •Multiple classes per file
    •Static methods not needed

    View Slide

  41. View Slide

  42. integer division

    View Slide

  43. integer division

    View Slide

  44. integer division

    View Slide

  45. integer division

    View Slide

  46. mutable defaults

    View Slide

  47. mutable defaults

    View Slide

  48. mutable defaults

    View Slide

  49. mutable defaults

    View Slide

  50. names and objects

    View Slide

  51. names and objects

    View Slide

  52. names and objects

    View Slide

  53. names and objects

    View Slide

  54. Demo
    http://people.csail.mit.edu/pgbovine/python/tutor.html

    View Slide

  55. class attributes

    View Slide

  56. class attributes

    View Slide

  57. class attributes

    View Slide

  58. View Slide

  59. Circular references
    •Misleading errors messages
    •Environment-specific
    •Divide and conquer

    View Slide

  60. The good stuff

    View Slide

  61. Interpreter
    console

    View Slide

  62. ipython

    View Slide

  63. pdb

    View Slide

  64. pdb

    View Slide

  65. pdb

    View Slide

  66. pip

    View Slide

  67. pip

    View Slide

  68. pip

    View Slide

  69. virtualenn
    •virtualenvwrapper
    •workon django
    virtualenv

    View Slide

  70. Testing
    •unittest ~ JUnit
    •nose, mock, coverage,
    pyhamcrest, twill, lettuce,
    tox

    View Slide

  71. View Slide

  72. docs

    View Slide

  73. server
    runserver

    View Slide

  74. admin

    View Slide

  75. class-based views

    View Slide

  76. View Slide

  77. 1. Placing the project's primary focus on
    the core domain and domain logic

    View Slide

  78. 1. Placing the project's primary focus on
    the core domain and domain logic
    2. Basing complex design on a model

    View Slide

  79. 1. Placing the project's primary focus on
    the core domain and domain logic
    2. Basing complex design on a model
    3. Developers and domain experts
    collaborate to iteratively improve the
    model

    View Slide

  80. View Slide

  81. Models
    •Capture the “conceptual heart
    of the domain”
    •DB schema generated for you
    •Foundation for application

    View Slide

  82. “...where powerful new features unfold as
    corollaries to older features.”

    View Slide

  83. Libraries

    View Slide

  84. django-extensions
    •Various useful utilities
    •runserver_plus (demo)

    View Slide

  85. south
    •Database schema migrations
    •Data migrations
    •Not a magic bullet though

    View Slide

  86. debug-toolbar
    •Inspect SQL queries
    •Template contexts
    •Signals, logging, ...

    View Slide

  87. Tips
    •Do a pure python project
    •Read top questions on Stack
    Overflow
    •Get your IDE set-up

    View Slide

  88. Teams
    •Books
    •Pairing
    •Dojos and workshops

    View Slide

  89. Summary

    View Slide

  90. Python :)
    •Clean and readable
    •Low learning curve
    •Rich eco-system of tools
    and libraries

    View Slide

  91. Python :(
    •No-one wants to go back
    •Harder to hire
    •Low-lowel hosting

    View Slide

  92. Thanks

    View Slide