Share
Embed
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
Transcript
70 slides
-
{ The COOLEST is yet TO COME “event”:
“PDI DEVCON 2013” “author”: “Pablo Enfedaque” “twi5er”: “pablitoev56” -
{ “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! -
{ “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 -
{ “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 -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The yield from statement -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Let’s implement itertools.chain -
{ “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] -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The new exception chaining -
{ “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") -
{ “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 -
{ “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 -
{ “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") -
{ “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 -
{ “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") -
{ “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 -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Single-‐‑dispatch generic functions -
{ “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() -
{ “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 -
{ “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() -
{ “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 -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Python virtual environments -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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) -
{ “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' -
{ “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 -
{ “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 -
{ “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 -
{ “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 -
{ “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) -
{ “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 -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Q&A Are we done yet? -
{ “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? -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Q&A Should we move now to Python 3? -
{ “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? -
{ “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 -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
The long journey to Python 3 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Meanwhile, most of the community -
{ “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 -
{ “event”: “PDI DEVCON 2013”, “author”: “Pablo Enfedaque”, “twi5er”: “pablitoev56”}
Q&A Thanks for coming! Slides: h5p://goo.gl/Yrzt0Q Code: h5p://goo.gl/V9bv72