thinking hard about_python
DESCRIPTION
My keynote speech from EuroPython, this talk explores what it is like being a developer in a community filled with experts from around the world. The goal of the talk is to provide useful content for beginners and topics of discussion for more advanced developers, while also focusing on Python’s strengths. Video of this talk is at http://www.youtube.com/watch?v=7TImWbnUDeITRANSCRIPT
![Page 1: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/1.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Daniel Greenfeld
!inking Hard About Python
![Page 2: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/2.jpg)
Daniel Greenfeldpydanny.com / @pydanny
@pydanny
![Page 3: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/3.jpg)
Daniel Greenfeldpydanny.com / @pydanny
http://2scoops.org
Danny: 128,546++Audrey: 121,871++
![Page 4: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/4.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What I want you to think of me. One Cartwheel of Many Around the World
![Page 5: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/5.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What I’m
really like. Myself at 13 in front of the Apple ][
![Page 6: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/6.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Overview
![Page 7: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/7.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Codinginto
Trouble
![Page 8: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/8.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Controversy
![Page 9: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/9.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Exceptions
![Page 10: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/10.jpg)
Daniel Greenfeldpydanny.com / @pydanny
AvoidingTechnical
Debt
![Page 11: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/11.jpg)
Daniel Greenfeldpydanny.com / @pydanny
..."rst section...
![Page 12: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/12.jpg)
Codinginto
Trouble
![Page 13: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/13.jpg)
Daniel Greenfeldpydanny.com / @pydanny
a.k.a.
![Page 14: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/14.jpg)
Super() Troubles
![Page 15: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/15.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Circle
The super method calls the parent class, which is Circle
import mathclass Circle(object):
def __init__(self, radius): self.radius = radius
def area(self): return self.radius ** 2 *math.pi
def __repr__(self): return '{0} as area {1}'.format( self.__class__.__name__, self.area() )
class Donut(Circle):
def __init__(self, outer, inner): super().__init__(outer) self.inner = inner
def area(self): outer, inner = self.radius, self.inner return Circle(outer).area() - Circle(inner).area()
What if our inheritanceisn’t simple?
>>> Circle(10)Circle as area 314.159265359
>>> Donut(10, 5)235.619449019
Superclassing is so easy!
![Page 16: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/16.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Contention
The super() method can create ambiguity.
![Page 17: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/17.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Example:
Django
![Page 18: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/18.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Class Based Generic Views
• Composition
• Inheritance
• Subclassing
• Polymorphism
• Lots of other big words used to impress other developers, students, your boss, your
doctor, Capoiera mestre, dog, cat, friends, family, and other people who generally don’t care about such things.
![Page 19: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/19.jpg)
Daniel Greenfeldpydanny.com / @pydanny
However...
![Page 20: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/20.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!ings I don’t know:
!e ancestor chain for
django.views.generic.edit.UpdateView
![Page 21: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/21.jpg)
Daniel Greenfeldpydanny.com / @pydanny
django.views.generic.edit.UpdateViewdjango.views.generic.detail.SingleObjectTemplateResponseMixindjango.views.generic.base.TemplateResponseMixindjango.views.generic.edit.BaseUpdateViewdjango.views.generic.edit.ModelFormMixindjango.views.generic.edit.FormMixindjango.views.generic.detail.SingleObjectMixindjango.views.generic.edit.ProcessFormViewdjango.views.generic.base.View
The ancestor chain for django.views.generic.edit.UpdateView:
![Page 22: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/22.jpg)
Daniel Greenfeldpydanny.com / @pydanny
def form_valid(self, form): verb_form = verb_form_base(self.request.POST) if verb_form.is_valid(): form.instance.verb_attributes = verb_form.cleaned_data return super().form_valid(form)
A form_valid() implementation
OMG Which form_valid() am I calling?
![Page 23: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/23.jpg)
Daniel Greenfeldpydanny.com / @pydanny
class ActionUpdateView( LoginRequiredMixin, # django-braces ActionBaseView, # inherits from AuthorizedForProtocolMixin AuthorizedforProtocolEditMixin, # Checks rights on edit views VerbBaseView, # Gets one of 200+ verb forms UpdateView): # django.views.generic.BaseView
def form_valid(self, form): verb_form = verb_form_base(self.request.POST) if verb_form.is_valid(): form.instance.verb_attributes = verb_form.cleaned_data return super().form_valid(form)
A form_valid() implementationOMG!
OMG!
OMG!
![Page 24: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/24.jpg)
Daniel Greenfeldpydanny.com / @pydanny
from actions.views import ActionUpdateViewfor x in ActionUpdateView.mro(): print(x)
Ancestor Chain (MRO) of ActionUpdateView
MRO = Method Resolution Order
Print the MRO
![Page 25: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/25.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Ancestor Chain (MRO)
<class 'actions.views.ActionUpdateView'><class 'braces.views.LoginRequiredMixin'><class 'actions.views.ActionBaseView'><class 'core.views.AuthorizedForProtocolMixin'><class 'core.views.AuthorizedforProtocolEditMixin'><class 'verbs.views.VerbBaseView'><class 'django.views.generic.edit.UpdateView'><class 'django.views.generic.detail.SingleObjectTemplateResponseMixin'><class 'django.views.generic.base.TemplateResponseMixin'><class 'django.views.generic.edit.BaseUpdateView'><class 'django.views.generic.edit.ModelFormMixin'><class 'django.views.generic.edit.FormMixin'><class 'django.views.generic.detail.SingleObjectMixin'><class 'django.views.generic.edit.ProcessFormView'><class 'django.views.generic.base.View'><type 'object'>
![Page 26: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/26.jpg)
Daniel Greenfeldpydanny.com / @pydanny
from actions.views import ActionUpdateViewfor x in [x for x in ActionUpdateView.mro() if hasattr(x, "form_valid")]: print(x)
Ancestor Chain (MRO) of ActionUpdateView
Filter the MRO list to only include classes with a form_valid() nethod
![Page 27: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/27.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Ancestor Chain (MRO) of
<class 'actions.views.ActionUpdateView'><class 'django.views.generic.edit.UpdateView'><class 'django.views.generic.edit.BaseUpdateView'><class 'django.views.generic.edit.ModelFormMixin'><class 'django.views.generic.edit.FormMixin'>
super’s chosenform_valid() ancestor
Current class
![Page 28: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/28.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Whew!
![Page 29: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/29.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Safe!
![Page 30: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/30.jpg)
Daniel Greenfeldpydanny.com / @pydanny
If you’re not careful, super can cause subtle
inheritance/MRO problems.
![Page 31: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/31.jpg)
Daniel Greenfeldpydanny.com / @pydanny
• Hope that anyone else maintaining this project isn’t going to kill me.
• Convert to a functional view.
• Explore better patterns.
Possible mitigations for this view.
• return UpdateView.form_valid(self, form)
![Page 32: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/32.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Write a easy-to-use MRO inspector thingee that identi"es the parent
attributes/methods speci"ed by the coder.
TODO
![Page 33: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/33.jpg)
Controversy
![Page 34: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/34.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Special cases aren’t special enough to break the rules.
Although practicality beats purity.*
* Zen of Python, lines 8 and 9
![Page 35: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/35.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Zen of Python$ python -c “import this”!e Zen of Python, by Tim Peters
Beautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.!ere should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at "rst unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!
PEP-0020
![Page 36: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/36.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Special cases aren’t special enough to break the rules.
Although practicality beats purity.*
* Zen of Python, lines 8 and 9
![Page 37: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/37.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Web2pyOften honors Implicit over Explicit
Follows its own namespace pattern
![Page 38: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/38.jpg)
Daniel Greenfeldpydanny.com / @pydanny
# encoding: utf-8# https://github.com/mdipierro/evote/blob/master/models/menu.py# this file is released under public domain and # you can use without limitations
response.title = 'Voting Service'response.subtitle = None
## read more at http://dev.w3.org/html5/markup/meta.name.htmlresponse.meta.author = 'Your Name <[email protected]>'response.meta.description = 'a cool new app'response.meta.keywords = 'web2py, python, framework'response.meta.generator = 'Web2py Web Framework'
# snip more content that I cut in the name of brevity
Web2py code sample
![Page 39: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/39.jpg)
Daniel Greenfeldpydanny.com / @pydanny
# encoding: utf-8# https://github.com/mdipierro/evote/blob/master/models/menu.py# this file is released under public domain and # you can use without limitations
response.title = 'Voting Service'response.subtitle = None
## read more at http://dev.w3.org/html5/markup/meta.name.htmlresponse.meta.author = 'Your Name <[email protected]>'response.meta.description = 'a cool new app'response.meta.keywords = 'web2py, python, framework'response.meta.generator = 'Web2py Web Framework'
# snip more content that I cut in the name of brevity
Web2py code sample
I GET IT NOW
Europe taught mewhy unicode is
important.
![Page 40: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/40.jpg)
Daniel Greenfeldpydanny.com / @pydanny
# encoding: utf-8# https://github.com/mdipierro/evote/blob/master/models/menu.py# this file is released under public domain and # you can use without limitations
response.title = 'Voting Service'response.subtitle = None
## read more at http://dev.w3.org/html5/markup/meta.name.htmlresponse.meta.author = 'Your Name <[email protected]>'response.meta.description = 'a cool new app'response.meta.keywords = 'web2py, python, framework'response.meta.generator = 'Web2py Web Framework'
# snip more content that I cut in the name of brevity
Web2py code sample
OK, Back to the talk...
![Page 41: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/41.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Web2py code sample# encoding: utf-8# https://github.com/mdipierro/evote/blob/master/models/menu.py# this file is released under public domain and # you can use without limitations
response.title = 'Voting Service'response.subtitle = None
## read more at http://dev.w3.org/html5/markup/meta.name.htmlresponse.meta.author = 'Your Name <[email protected]>'response.meta.description = 'a cool new app'response.meta.keywords = 'web2py, python, framework'response.meta.generator = 'Web2py Web Framework'
# snip more content that I cut in the name of brevity
Response object magically exists.No import necessary
What can I expect in any location?What about namespace pollution?
Written by Massimo himself
![Page 42: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/42.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Contention• Explicit is better than implicit
• In the name of ambiguity, refuse the temptation to guess
• Namespaces are one honking great idea -- let's do more of those!
Web2py violates these 3 koans:
* Zen of Python, lines 2, 12, 19
![Page 43: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/43.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Controversy
Special cases aren’t special enough to break the rules.Although practicality beats purity.*
* Zen of Python, lines 8, 9
![Page 44: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/44.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Special cases aren’t special enough to break the rules.Although practicality beats purity.*
Web2py contends:
* Zen of Python, lines 8, 9
![Page 45: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/45.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Web2py contends:
• Implicit behaviors means Web2py is easier for beginners to learn.
• !e Web2py namespace pattern is easy to learn.
• For experienced developers, commonly repeated imports are boilerplate.
Note: This is my interpretation of Web2py design considerations.
Personal side note: Web2py is very easy to install.
![Page 46: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/46.jpg)
Daniel Greenfeldpydanny.com / @pydanny
And that’s okay
Web2py will always be contentious
Web2py argues practicalityin some very specific places.
Controversy
Special cases aren’t special enough to break the rules.Although practicality beats purity.
![Page 47: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/47.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Flask and its global Request objecthttp://bit.ly/flask-requests
A Little Magic Goes a Long Way
![Page 48: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/48.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Flask and its global Request objecthttp://bit.ly/flask-requests
A Little Magic Goes a Long Way
![Page 49: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/49.jpg)
Exceptions
![Page 50: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/50.jpg)
SilentExceptions
are the
Devil
![Page 51: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/51.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Exceptions
Errors should never pass silently.Unless explicitly silenced.*
* Zen of Python, lines 10 and 11
![Page 52: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/52.jpg)
Daniel Greenfeldpydanny.com / @pydanny
djangopackages.com• Once a day iterates across all
packages.
• Updates the metadata from:
• Github:
• Bitbucket
• PyPI
![Page 53: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/53.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Django Packages
• Sometimes the APIs go down.
• Sometimes the APIs change.
• Sometimes projects get deleted.
• Sometimes the Internets fail
Problems
Catch and report exceptions!
![Page 54: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/54.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Old package_updater.py...for package in Package.objects.all(): try: package.fetch_metadata() package.fetch_commits() except socket_error, e: text += "\nFor '%s', threw a socket_error: %s" % \
(package.title, e) continue # snip lots of other exceptions except Exception as e: text += "\nFor '%s', General Exception: %s" % \
(package.title, e) continue
# email later
https://github.com/opencomparison/opencomparison/blob/master/package/management/commands/package_updater.py
http://bit.ly/Q8v9xk
Um...
![Page 55: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/55.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What I was doing
>>> try:... a = b... except Exception as e:... print(e)...name 'b' is not defined
What’s the error type?!?
Where is my stack trace?!?
(and it’s wrong)
![Page 56: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/56.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What I wanted
>>> a = bTraceback (most recent call last): File "<stdin>", line 1, in <module>NameError: name 'b' is not defined
Traceback
Error typeError message
![Page 57: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/57.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Exceptions
Errors should never pass silently.Unless explicitly silenced.*
My code is nearly silent
I’ve silenced things for no good reason
* Zen of Python, lines 10 and 11
![Page 58: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/58.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Getting what I want>>> class CustomErrorHandler(Exception):... def __init__(self, error):... print(error)... print(type(error))...>>> try:... a=b... except Exception as e:... raise CustomErrorHandler(e)...name 'b' is not definedTraceback (most recent call last): File "<stdin>", line 4, in <module>__main__.CustomErrorHandlerNameError
Traceback
Error message
For this exampleprint == log
No color because it’s a print statement
Error Type
![Page 59: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/59.jpg)
Daniel Greenfeldpydanny.com / @pydanny
PackageUpdaterException
Nice message
Full traceback
All errors caught
class PackageUpdaterException(Exception): def __init__(self, error, title): log_message = "For {title}, {error_type}: {error}".format( title=title, error_type=type(error), error=error ) logging.error(log_message) logging.exception(error)
for package in Package.objects.all(): try: try: package.fetch_metadata() package.fetch_commits() except Exception as e: raise PackageUpdaterException(e, package.title) except PackageUpdaterException: continue
Loop forward
![Page 60: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/60.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Exceptions
Errors should never pass silently.Unless explicitly silenced.
My code is nearly silent
I’ve silenced things for no good reason
![Page 61: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/61.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Exceptions
Errors should never pass silently.Unless explicitly silenced.
![Page 62: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/62.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Next up...
![Page 63: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/63.jpg)
The Dutch Way
![Page 64: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/64.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Decorators@memoizedef allcaps(string): return string.upper()
def allcaps(string): return string.upper()
allcaps = memoize(allcaps)>
Decorators are easy to explain!
“A decorator is a function that returns a function.”
![Page 65: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/65.jpg)
Daniel Greenfeldpydanny.com / @pydanny
I am ZenDecorators == Zen of Python
![Page 66: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/66.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Until...
![Page 67: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/67.jpg)
Daniel Greenfeldpydanny.com / @pydanny
I am not ZenI need to write a decorator.
![Page 68: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/68.jpg)
Daniel Greenfeldpydanny.com / @pydanny
You try to shoot yourself in the foot, only to realize there’s no need, since Guido
thoughtfully shot you in the foot years ago.
-- Nick Mathewson, comp.lang.python
http://starship.python.net/~mwh/quotes.html
Ouch
![Page 69: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/69.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Decorators@memoizedef allcaps(string): return string.upper()
def allcaps(string): return string.upper()
allcaps = memoize(allcaps)>
Decorators are easy to explain!
“A decorator is a function that returns a function.”
![Page 70: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/70.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Decorator Template
http://pydanny-event-notes.readthedocs.org/en/latest/SCALE10x/python-decorators.html#decorator-template
def decorator(function_to_decorate): def wrapper(*args, **kwargs): # do something before invoation result = func_to_decorate(*args, **kwargs)
# do something after return result # update wrapper.__doc__ and .func_name # or functools.wraps return wrapper
Result is returned when the wrapper is done
When decorated function iscalled decorator returns wrapper
Wrapper function does things before
and after the function is called here.
Wrapper function does things before
and after the function is called here.
![Page 71: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/71.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!e Dutch WayThere should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.*
* Zen of Python, lines 13 and 14
![Page 72: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/72.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Decorator implementation
def memoize(func): cache = {}
def memoized(*args): if args in cache: return cache[args] result = cache[args] = func(*args) return result
return memoized
@memoizedef allcaps(string): return string.upper()
Return function
Return value
set cache
Return value if args in cache
Datastore
![Page 73: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/73.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Whew.
![Page 74: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/74.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What about decoratorsthat accept arguments?
![Page 75: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/75.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Oh No.
![Page 76: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/76.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Explaining this is
Hard.!at’s because we create a decorator that creates a
parameterized function to wrap the function.
![Page 77: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/77.jpg)
Daniel Greenfeldpydanny.com / @pydanny
multiplier decorator
def multiplier(multiple): def decorator(function): def wrapper(*args, **kwargs): return function(*args, **kwargs) * multiple return wrapper return decorator
@multiplier(5)def allcaps(string): return string.upper()
Multiplier function sets the state for the multiple
argument
When decorated function is called the decorator function returns the wrapper function
Result is returned when the wrapper is done.
Wrapper function does:
What am I supposed to highlight?
![Page 78: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/78.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Whew
![Page 79: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/79.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Oh No.
![Page 80: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/80.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Not Done Yet!
![Page 81: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/81.jpg)
Daniel Greenfeldpydanny.com / @pydanny
authentication decorator
@authorization('admin')def do_admin_thing(user): # do something administrative return user
import functoolsdef authorization(roles): def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs): check_roles(user, roles) return function(*args, **kwargs) return wrapper return decorator
Don’t forget functools!
![Page 82: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/82.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Whew
![Page 83: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/83.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Really.
![Page 84: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/84.jpg)
Daniel Greenfeldpydanny.com / @pydanny
I’m not doing class decorators.
![Page 85: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/85.jpg)
Daniel Greenfeldpydanny.com / @pydanny
It is not easy to explain how
to write decorators.
![Page 86: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/86.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Contention
While Usingdecorators is
Zen...
![Page 87: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/87.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Contention
Writing Decorators
is Not.
![Page 88: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/88.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Deep !ought
There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.
If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.
Although practicality beats purity.
Decorators are easy to explain!
Decorators are hard to explain!
![Page 89: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/89.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Use the decorator library
https://pypi.python.org/pypi/decorator
![Page 90: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/90.jpg)
AvoidingTechnical
DebtPart I
![Page 91: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/91.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Getting it done vs.
Technical debt
Now is better than never.Although never is often better than *right* now.
* Zen of Python, lines 15 and 16
![Page 92: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/92.jpg)
Daniel Greenfeldpydanny.com / @pydanny
• Tests
• Documentation
Some things take time
Risk: Deploying broken code
Risk: problems upgrading dependencies
Risk: Forgetting install/deploy
Risk: Multiple coding standards
(Risks of skipping them)
![Page 93: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/93.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Easy Test Patterns
• Always make sure your test harness can run
• Try using tests instead of the shell/repl.
• After the "rst deadline, reject any incoming code that drops coverage.
• Use coverage.py
For developers racing to meet deadlines:
![Page 94: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/94.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Must-have Documentation
• Installation/Deployment procedures
• Coding standards
• How to run tests
• Version (including __version__)
![Page 95: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/95.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Easy Test Patterns
• Always make sure your test harness can run
• Try using tests instead of the shell/repl.
• Reject any incoming code that drops coverage.
• Use coverage.py
![Page 96: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/96.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Getting technical again...
![Page 97: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/97.jpg)
AvoidingTechnical
DebtPart II
![Page 98: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/98.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Namespaces
• Extremely powerful
• Useful
• Precise
import reimport os
from twisted.internet import protocol, reactor
from django import formsfrom myproject import utils
![Page 99: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/99.jpg)
Daniel Greenfeldpydanny.com / @pydanny
import * makesdevelopment faster[1]
• Extremely powerful
• Useful
• Imports everything at once! [2]
from re import *from os import *from twisted import *from django.forms import *from myproject.utils import *
[1]Warning: import * can be dangerous
[2]Warning: import * can be dangerous
![Page 100: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/100.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Comparing two modulesdef compare(mod1, mod2): title = '\nComparing {0}, {1}:'.format( mod1.__name__, mod2.__name__ ) print(title) for x in dir(mod1): for y in dir(mod2): if x == y and not x.startswith('_'): print("* " + x)
![Page 101: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/101.jpg)
Daniel Greenfeldpydanny.com / @pydanny
>>> re.sys == os.sysTrue
>>> re.error == os.errorFalse
Comparing two modules
>>> import re>>> import os
>>> compare(os, re)Comparing os, re:* sys* error
import * can get you into trouble
from re import *from os import *
![Page 102: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/102.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Breaking built-ins
def compare_builtins(mod1): print("\nComparing {0} to builtins:".format(mod1.__name__)) for x in dir(mod1): for y in dir(globals()['__builtins__']): if x == y and not x.startswith('_'): print("* GLOBAL: {0}".format(x))
Checks to see if a module has itemsthat match any Python built-in.
![Page 103: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/103.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Breaking built-ins
>>> compare_builtins(re)Comparing re to builtins:* GLOBAL: compile
>>> compare_builtins(os)Comparing os to builtins:* GLOBAL: open
from re import *from os import *
Breaks compile() built-in.
Annoying but infrequent problem.
Breaks open() built-in.
!is can drive you crazy.
Compare ‘re’ Compare ‘os’
![Page 104: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/104.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!e open() story
from os import *after
before
Breaks allthe
things!
Help on built-in function open in module __builtin__:
open(...) open(name[, mode[, buffering]]) -> file object
Open a file using the file() type, returns a file object. This is the preferred way to open a file. See file.__doc__ for further information.
Help on built-in function open in module posix:
open(...) open(filename, flag [, mode=0777]) -> fd
Open a file (for low level IO).
![Page 105: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/105.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Beginner pro-tip
Be careful of tutorials that use import *.
![Page 106: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/106.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Contention
import * is not for beginners.
import * is people who really know Python.
__all__ = ["echo", "surround", "reverse"]
![Page 107: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/107.jpg)
Summary
![Page 108: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/108.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Staythis
personMyself at 13 in front of the Apple ][
![Page 109: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/109.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Admit What You Don't
Know
![Page 110: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/110.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Stay out of your comfort
Zone
![Page 111: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/111.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Grow
![Page 112: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/112.jpg)
Daniel Greenfeldpydanny.com / @pydanny
What I Want To Know
• Twisted• Numpy• SciPy
• Tulip• C • Etc.
![Page 113: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/113.jpg)
Daniel Greenfeldpydanny.com / @pydanny
If I continue to Learn
![Page 114: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/114.jpg)
Daniel Greenfeldpydanny.com / @pydanny
I Get To Be !is
Person
![Page 115: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/115.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!inkHard
![Page 116: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/116.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!ank you
• Armin Ronacher
• nephila.it
• Richard Jones
• Raymond Hettiger
• EuroPython
• PyKonik
• Łukasz Langa
• Tomasz Paczkowski
![Page 117: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/117.jpg)
Daniel Greenfeldpydanny.com / @pydanny
!ank you
• Matt Harrison
• Ola Sendecka
• Kenneth Love
• Lennart Regebro
• Paul Hildebrandt
• Audrey Roy
![Page 118: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/118.jpg)
Daniel Greenfeldpydanny.com / @pydanny
One More!ing...
![Page 119: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/119.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Finis
![Page 120: Thinking hard about_python](https://reader033.vdocuments.net/reader033/viewer/2022060108/554dae0cb4c905fa7a8b4f8e/html5/thumbnails/120.jpg)
Daniel Greenfeldpydanny.com / @pydanny
Q & A