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

Python: the coolest is yet to come

Pablo E
November 05, 2013

Python: the coolest is yet to come

In this talk we will make a tour through the most important changes and new features in the language and its standard library, such as enums, single-dispatch generic functions, Tulip, yield from, raise from None, contextlib... And yes, we will talk about Python 3.

GitHub repository with the code of the examples: https://github.com/pablito56/coolest_is_yet_to_come

Pablo E

November 05, 2013
Tweet

More Decks by Pablo E

Other Decks in Programming

Transcript

  1. { The  COOLEST  is  yet   TO  COME “event”:  

       “PDI  DEVCON  2013” “author”:  “Pablo  Enfedaque” “twi5er”:  “pablitoev56”
  2. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Today  we  are  going  to  see  a  quick  tour  through   Python’s  newest  features >  The  new  super  function >  The  yield  from  statement >  The  new  exception  chaining >  Single-­‐‑dispatch  generic  functions >  Python  virtual  environments >  The  enum  module >  The  asyncio  module >  And  lots  of  other  new  features Welcome!
  3. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  SilentDict class SilentDict(dict): def __getitem__(self, key): """Called to implement evaluation of self[key] :returns: None by default """ try: return super(SilentDict, self).__getitem__(key) except KeyError: return None >>> d = SilentDict() >>> print (d[“a”]) None >>> d = SilentDict({"a": 1, "b": 2}) >>> print(d["a"]) 1 >>> print(d["a"]) None
  4. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  SilentDict class SilentDict(dict): def __getitem__(self, key): """Called to implement evaluation of self[key] :returns: None by default """ try: return super().__getitem__(key) except KeyError: return None >>> d = SilentDict() >>> print (d[“a”]) None >>> d = SilentDict({"a": 1, "b": 2}) >>> print(d["a"]) 1 >>> print(d["a"]) None
  5. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  h5p://docs.python.org/3/library/ functions.html#super >  PEP  3135:  New  Super >  h5p://www.python.org/dev/peps/pep-­‐‑3135/ >  Introduced  in  Python  3.0 >  Standard  Library  updated  to  use  it >  No  official  backport The  super  function
  6. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  itertools.chain def chain(*iterables): # chain('ABC', 'DEF') --> A B C D E F for it in iterables: yield from it >>> list(chain('ABC', 'DEF')) ['A', 'B', 'C', 'D', 'E', 'F'] >>> list(chain([1, 2, 3], (4, 5, 6), [7, 8, 9])) [1, 2, 3, 4, 5, 6, 7, 8, 9]
  7. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  PEP  380:  Syntax  for  Delegating  to  a  Subgenerator >  h5p://www.python.org/dev/peps/pep-­‐‑0380/ >  Introduced  in  Python  3.3 >  No  backport The  yield  from  statement
  8. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining from urllib.request import urlopen from urllib.error import URLError class CustomException(Exception): """Out custom exception for this example""” def requester(url): """Open and read given url""" try: return urlopen(url).readall() except URLError: raise CustomException def call_the_requester(url): return requester(url) def main_app(url): print(call_the_requester(url)) if __name__ == "__main__": main_app("http://unknown_host:8765")
  9. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining $ python3.4 raise_from_none_examples.py Traceback (most recent call last): ... File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/urllib/ request.py", line 1255, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known> During handling of the above exception, another exception occurred: Traceback (most recent call last): File "raise_from_none_examples.py", line 39, in <module> main_app("http://unknown_host:8765") File "raise_from_none_examples.py", line 35, in main_app print(call_the_requester(url)) File "raise_from_none_examples.py", line 31, in call_the_requester return requester(url) File "raise_from_none_examples.py", line 27, in requester raise CustomException __main__.CustomException
  10. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining $ python3.4 raise_from_none_examples.py Traceback (most recent call last): ... File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/urllib/ request.py", line 1255, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known> During handling of the above exception, another exception occurred: Traceback (most recent call last): File "raise_from_none_examples.py", line 39, in <module> main_app("http://unknown_host:8765") File "raise_from_none_examples.py", line 35, in main_app print(call_the_requester(url)) File "raise_from_none_examples.py", line 31, in call_the_requester return requester(url) File "raise_from_none_examples.py", line 27, in requester raise CustomException __main__.CustomException
  11. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining from urllib.request import urlopen from urllib.error import URLError class CustomException(Exception): """Out custom exception for this example""” def requester(url): """Open and read given url""" try: return urlopen(url).readall() except URLError as exc: raise CustomException from exc def call_the_requester(url): return requester(url) def main_app(url): print(call_the_requester(url)) if __name__ == "__main__": main_app("http://unknown_host:8765")
  12. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining $ python3.4 raise_from_none_examples.py Traceback (most recent call last): ... File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/ request.py", line 1242, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "raise_from_none_examples.py", line 40, in <module> main_app("http://unknown_host:8765") File "raise_from_none_examples.py", line 36, in main_app print(call_the_requester(url)) File "raise_from_none_examples.py", line 32, in call_the_requester return requester(url) File "raise_from_none_examples.py", line 28, in requester raise CustomException from exc __main__.CustomException
  13. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining from urllib.request import urlopen from urllib.error import URLError class CustomException(Exception): """Out custom exception for this example""” def requester(url): """Open and read given url""" try: return urlopen(url).readall() except URLError: raise CustomException from None def call_the_requester(url): return requester(url) def main_app(url): print(call_the_requester(url)) if __name__ == "__main__": main_app("http://unknown_host:8765")
  14. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    The  new  exception  chaining $ python3.4 raise_from_none_examples.py Traceback (most recent call last): File "raise_from_none_examples.py", line 40, in <module> main_app("http://unknown_host:8765") File "raise_from_none_examples.py", line 36, in main_app print(call_the_requester(url)) File "raise_from_none_examples.py", line 32, in call_the_requester return requester(url) File "raise_from_none_examples.py", line 28, in requester raise CustomException from None __main__.CustomException
  15. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Several  PEPs  involved: >  PEP  3134:  Exception  Chaining  and  Embedded   Tracebacks >  h5p://www.python.org/dev/peps/pep-­‐‑3134 >  PEP  409:  Suppressing  exception  context >  h5p://www.python.org/dev/peps/pep-­‐‑0409/ >  PEP  415:  Implement  context  suppression  with   exception  a5ributes >  h5p://www.python.org/dev/peps/pep-­‐‑0415 >  Introduced  in  Python  3.0  and  3.3 >  No  official  backport The  new  exception  chaining
  16. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  create  some  animals class Duck: def quack(self): print("quack") class Cat: def meow(self): print("meow") class Dog: def bark(self): print("bark”) class Cow: def moo(self): print("moo") donald = Duck() garfield = Cat() milu = Dog() milka = Cow()
  17. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  play  animals’  sounds def make_sound(animal): if isinstance(animal, Duck): animal.quack() elif isinstance(animal, Cat): animal.meow() elif isinstance(animal, Dog): animal.bark() else: raise NotImplementedError("Unknown animal") >>> make_sound(donald) quack >>> make_sound(garfield) meow >>> make_sound(milu) bark >>> make_sound(milka) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 11, in make_sound NotImplementedError: Unknown animal
  18. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Single-­‐‑dispatch  generic  functions import functools @functools.singledispatch def make_sound(animal): raise NotImplementedError("Unknown animal") @make_sound.register(Duck) def make_duck_sound(animal): animal.quack() @make_sound.register(Cat) def make_cat_sound(animal): animal.meow() @make_sound.register(Dog) def _(animal): animal.bark()
  19. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Single-­‐‑dispatch  generic  functions >>> make_sound(donald) quack >>> make_sound(garfield) meow >>> make_sound(milu) bark >>> make_sound(milka) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.4/lib/ python3.4/functools.py", line 632, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "<stdin>", line 5, in make_sound NotImplementedError: Unknown animal
  20. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  h5p://docs.python.org/dev/library/ functools.html#functools.singledispatch >  PEP  443:  Single-­‐‑dispatch  generic  functions >  h5p://www.python.org/dev/peps/pep-­‐‑0443/ >  Introduced  in  Python  3.4 >  No  official  backport Single-­‐‑dispatch  generic  functions
  21. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Python  virtual  environments $ pyvenv /tmp/test_venv $ ls /tmp/test_venv/ bin include lib pyvenv.cfg $ ls /tmp/test_venv/bin/ activate activate.csh activate.fish python python3 python3.4 $ cat /tmp/test_venv/pyvenv.cfg home = /Library/Frameworks/Python.framework/Versions/3.4/bin include-system-site-packages = false version = 3.4.0 $ pyvenv /tmp/test_venv --symlinks --clear --system-site-packages $ cat /tmp/test_venv/pyvenv.cfg home = /Library/Frameworks/Python.framework/Versions/3.4/bin include-system-site-packages = true version = 3.4.0 $ ls -lAhtr /tmp/test_venv/bin/python3.4 lrwxr-xr-x 1 pev wheel 63B 5 nov 00:21 /tmp/test_venv/bin/python3.4 -> / Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4
  22. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Python  virtual  environments $ source /tmp/test_venv/bin/activate (test_venv) ...$ which python /tmp/test_venv/bin/python (test_venv) ...$ which python3.4 /tmp/test_venv/bin/python3.4 (test_venv) ...$ python Python 3.4.0a4 (v3.4.0a4:e245b0d7209b, Oct 20 2013, 02:43:50) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.prefix, sys.base_prefix ('/private/tmp/test_venv', '/Library/Frameworks/Python.framework/Versions/3.4') >>> sys.exec_prefix, sys.base_exec_prefix ('/private/tmp/test_venv', '/Library/Frameworks/Python.framework/Versions/3.4') (test_venv) ...$ deactivate $ which python /usr/bin/python
  23. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Features >  Supports  symbolic  links  (recommended) >  Access  both  environment  and  system  site-­‐‑packages   >  pyvenv.cfg  environment  configuration  file: >  home:  path  to  original  Python  installation  bin >  include-­‐‑system-­‐‑site-­‐‑packages:  access  system  site-­‐‑packages   after  the  environment  site-­‐‑packages >  version:  Python  version  in  use >  Public  API  to  let  3rd  party  virtual  environments  customise   the  environment  creation >  Subclass  EnvBuilder  and  redefine  desired  methods Python  virtual  environments
  24. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  h5p://docs.python.org/3/library/venv.html >  PEP  405:  Python  Virtual  Environments >  h5p://www.python.org/dev/peps/pep-­‐‑0405/ >  Introduced  in  Python  3.3 >  No  official  backport,  although  quite  similar  to   virtualenv Python  virtual  environments
  25. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  traffic  light RED, ORANGE, GREEN = range(3) # Colors STOPPED, RUNNING = range(2) # Statuses class TrafficLight: def __init__(self, light_color, status): assert light_color in (RED, ORANGE, GREEN), "Not a valid color" assert status in (RUNNING, STOPPED), "Not a valid status" self.color = light_color self.status = status def print_state(self): color_name = "red" if self.color == RED else "green" if self.color == GREEN else "orange" status_name = "running" if self.status == RUNNING else "stopped" print("Traffic light is {} in color {}".format(status_name, color_name)) >>> my_semaphore = TrafficLight(RUNNING, RED) >>> my_semaphore.print_state() Traffic light is stopped in color orange
  26. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  traffic  light RED, ORANGE, GREEN = range(3) # Colors STOPPED, RUNNING = range(2) # Statuses class TrafficLight: def __init__(self, light_color, status): assert light_color in (RED, ORANGE, GREEN), "Not a valid color" assert status in (RUNNING, STOPPED), "Not a valid status" self.color = light_color self.status = status def print_state(self): color_name = "red" if self.color == RED else "green" if self.color == GREEN else "orange" status_name = "running" if self.status == RUNNING else "stopped" print("Traffic light is {} in color {}".format(status_name, color_name)) >>> my_semaphore = TrafficLight(RUNNING, RED) >>> my_semaphore.print_state() Traffic light is stopped in color orange
  27. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  traffic  light RED, ORANGE, GREEN = range(3) # Colors STOPPED, RUNNING = range(2) # Statuses class TrafficLight: def __init__(self, light_color, status): assert light_color in (RED, ORANGE, GREEN), "Not a valid color" assert status in (RUNNING, STOPPED), "Not a valid status" self.color = light_color self.status = status def print_state(self): color_name = "red" if self.color == RED else "green" if self.color == GREEN else "orange" status_name = "running" if self.status == RUNNING else "stopped" print("Traffic light is {} in color {}".format(status_name, color_name)) >>> my_semaphore = TrafficLight(RUNNING, RED) >>> my_semaphore.print_state() Traffic light is stopped in color orange
  28. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Let’s  implement  a  traffic  light RED, ORANGE, GREEN = range(3) # Colors STOPPED, RUNNING = range(2) # Statuses class TrafficLight: def __init__(self, light_color, status): assert light_color in (RED, ORANGE, GREEN), "Not a valid color" assert status in (RUNNING, STOPPED), "Not a valid status" self.color = light_color self.status = status def print_state(self): color_name = "red" if self.color == RED else "green" if self.color == GREEN else "orange" status_name = "running" if self.status == RUNNING else "stopped" print("Traffic light is {} in color {}".format(status_name, color_name)) >>> STOPPED is RED and RUNNING is ORANGE True >>> (RUNNING + ORANGE) * GREEN 4
  29. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Introducing  the  enum  module from enum import Enum Color = Enum("Color", "red orange green") # Colors Status = Enum("Status", "stopped running") # Statuses class TrafficLight: def __init__(self, light_color, status): assert light_color in Color, "Not a valid color" assert status in Status, "Not a valid status" self.color = light_color self.status = status def print_state(self): color_name = "red" if self.color == Color.red else "green" if self.color == Color.green else "orange" status_name = "running" if self.status == Status.running else "stopped" print("Traffic light is {} in color {}".format(status_name, color_name)) my_semaphore = TrafficLight(Status.running, Color.red)
  30. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Introducing  the  enum  module >>> my_semaphore = TrafficLight(Status.running, Color.red) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __init__ AssertionError: Not a valid color >>> my_semaphore = TrafficLight(Color.red, Status.running) >>> my_semaphore.print_state() Traffic light is running in color red >>> Status.stopped is Color.red False >>> Status.running is Color.orange False >>> (Status.running + Color.orange) * Color.green Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'Status' and 'Color'
  31. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    More  about  enum  module class Color(Enum): # enumaration red = 0 orange = 10 # enumeration members green = 20 # custom non-consecutive values ruby = 0 # aliases >>> print(Color.green) Color.green >>> print(repr(Color.green)) <Color.green: 20> >>> print(repr(Color.ruby)) # this is an alias <Color.red: 0> >>> print(Color.orange.name) # we can retrieve a member name orange >>> print(Color["orange"]) # we can get the enum member from its name Color.orange >>> print(Color.orange.value) # we can retrieve a member value 10 >>> print(Color(10)) # we can get the enum member from its value Color.orange
  32. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    More  about  enum  module class Color(Enum): red = 0 orange = 10 green = 20 class Status(Enum): running = 0 stopped = 1 class TrafficLight: def __init__(self, light_color, status): assert light_color in Color, "Not a valid color" assert status in Status, "Not a valid status" self.color = light_color self.status = status def print_state(self): print("Traffic light is {} in color {}".format(self.status.name, self.color.name)) >>> my_semaphore = TrafficLight(Color.red, Status.running) >>> my_semaphore.print_state() Traffic light is running in color red
  33. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  And  still  more  features >  Iteration  over  enumeration  members >  Ordered  dictionary  __members__  special  a5ribute >  Define  methods  and  class  methods >  Even  redefine  __str__  or  __repr__ >  IntEnum  to  preserve  old  int  behaviour >  @enum.unique  to  enforce  no  aliases  are  defined >  Possibility  to  define  other  custom  Enum  sublcasses >  Functional  API More  about  enum  module
  34. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  h5p://docs.python.org/3.4/library/enum.html >  PEP  435:  Adding  an  Enum  type  to  the  Python   standard  library >  h5p://www.python.org/dev/peps/pep-­‐‑0435/ >  Introduced  in  Python  3.4 >  Standard  Library  updated  to  use  enums >  IntEnum  when  backwards-­‐‑compatibility  broken >  Enum  in  new  developments  and  internal  modules >  Official  backport  available  in  PyPi >  h5ps://pypi.python.org/pypi/enum34/   The  enum  module
  35. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Python’s  asynchronous  IO  Support  Rebooted >  No  new  language  features,  no  new  lib  extensions >  Based  on  a  customisable  event  loop >  Interface  to  manage  the  event  loop  and  its  policies >  Interface  to  implement  or  adapt  event  loops >  Different  3rd  party  async  frameworks  could  interoperate >  Coroutines,  futures  and  tasks >  Transports  and  protocols >  Use  yield  from  to  delegate  or  callbacks The  asyncio  module  (aka.  Tulip)
  36. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  h5p://docs.python.org/3.4/library/enum.html >  PEP  3156:  Asynchronous  IO  Support  Rebooted:   the  "ʺasyncio"ʺ  Module >  h5p://www.python.org/dev/peps/pep-­‐‑3156/ >  Reference  implementation  in  Python  3.4 >  Expected  final  status  in  Python  3.5 >  Backport  to  3.3  available  in  PyPi >  h5ps://pypi.python.org/pypi/asyncio/0.1.1 The  asyncio  module
  37. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  unicode,  unicode  everywhere >  generators,  generators  everywhere >  or  iterators >  uniNest.mock  (port  of  Michael  Foord’s  mock) >  contextlib.ExitStack  and  contextlib.ContextDecorator >  Be5er  GIL  (but  still  Global  Interpreter  Lock) >  concurrent.futures  for  async  computation >  Qualified  name  for  classes  and  functions >  selectors  module >  … And  still  lots  of  new  features
  38. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Not  yet >  Only  22  slides  missing >  16  only  with  pictures,  and  even  1  animated  GIF >  Sorry,  no  ki5ens Q&A Are  we  done  yet?
  39. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  YES >  Well,  maybe  NO >  Well,  let  me  explain Q&A Should  we  move  now  to   Python  3?
  40. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    h5p://www.python.org/download/releases/2.7/ Release  schedule: >  … >  2.7.0  final:  July  3,  2010 >  … >  2.7.6  candidate  1:  October  26,  2013 >  ??? >  2.7.X  end  of  support:  ≈  2016 Python  2.7
  41. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    h5p://www.python.org/download/releases/3.4.0/ Release  schedule: >  3.4.0  alpha  4:  October  20,  2013 >  3.4.0  beta  1  (feature  freeze):  November  24,  2013 >  3.4.0  beta  2:  January  5,  2014 >  3.4.0  candidate  1:  January  19,  2014 >  3.4.0  candidate  2:  February  2,  2014 >  3.4.0  final:  February  23,  2014 Python  3.4
  42. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    >  Great  features  are  waiting  us  in  Python  3 >  We  are  beyond  half  the  planned  life  of  Python  2.7 >  Python  2.6  is  officially  retired  with  2.6.9  release >  Most  3rd  party  dependencies  already  in  Python  3 >  Or  we  could  return  to  OSS  all  that  we  have  been  given >  Porting  to  Python  3  is  not  such  a  big  deal >  In  most  of  the  cases >  So,  no  more  excuses >  It’s  time  to  start  moving  to  Python  3 Conclusions
  43. {  “event”:  “PDI  DEVCON  2013”,  “author”:  “Pablo  Enfedaque”,  “twi5er”:  “pablitoev56”}

    Q&A Thanks  for  coming! Slides:  h5p://goo.gl/Yrzt0Q   Code:  h5p://goo.gl/V9bv72