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.

52d39c7b27386ca98bc016119d95b8b8?s=128

David Winterbottom

March 02, 2012
Tweet

Transcript

  1. Migrating from to and David Winterbottom @codeinthehole and

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

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

  5. Today •Introduction to Python •Introduction to Django

  6. None
  7. None
  8. Zen of python

  9. None
  10. None
  11. None
  12. What’s http://www.davidshrigley.com/photo_htmpgs/lost_pidgeon.html

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

  14. None
  15. None
  16. None
  17. Privacy •Nothing truly private •_name not in public API •__name

    mangled
  18. switch () {}

  19. None
  20. None
  21. OO •Type-hinting •Interfaces •Duck typing

  22. None
  23. Don’t check type

  24. Don’t check type

  25. None
  26. None
  27. None
  28. Server set-up • Easy: apache2, mod_php • Tricky: apache2, mod_wsgi,

    ... • ...but getting better: • Servers: gunicorn, uWSGI • Platforms: ep.io, gondor.io
  29. None
  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
  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
  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
  33. None
  34. TypeError >>> 'hello' + 100 Traceback (most recent call last):

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

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

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

    File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' objects >>> duck, dynamic, strong
  38. Data-structures •PHP: array() •tuple(), dict(), set(), list(), , ... •...

    deque(), defaultdict() - collections
  39. Inheritance multiple inheritance

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

  41. None
  42. integer division

  43. integer division

  44. integer division

  45. integer division

  46. mutable defaults

  47. mutable defaults

  48. mutable defaults

  49. mutable defaults

  50. names and objects

  51. names and objects

  52. names and objects

  53. names and objects

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

  55. class attributes

  56. class attributes

  57. class attributes

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

  60. The good stuff

  61. Interpreter console

  62. ipython

  63. pdb

  64. pdb

  65. pdb

  66. pip

  67. pip

  68. pip

  69. virtualenn •virtualenvwrapper •workon django virtualenv

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

    tox
  71. None
  72. docs

  73. server runserver

  74. admin

  75. class-based views

  76. None
  77. 1. Placing the project's primary focus on the core domain

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

    and domain logic 2. Basing complex design on a model
  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
  80. None
  81. Models •Capture the “conceptual heart of the domain” •DB schema

    generated for you •Foundation for application
  82. “...where powerful new features unfold as corollaries to older features.”

  83. Libraries

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

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

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

  87. Tips •Do a pure python project •Read top questions on

    Stack Overflow •Get your IDE set-up
  88. Teams •Books •Pairing •Dojos and workshops

  89. Summary

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

    of tools and libraries
  91. Python :( •No-one wants to go back •Harder to hire

    •Low-lowel hosting
  92. Thanks