Python for Web
                                by Alex Radchenko and Yegor Nazarkin,
                                                www.mediasapiens.co




twitter: @dixon_che, @nimnull
Who we are?
              Web solutions

                                         Flexible
      Pythonic
                       Development
           Neat                        OpenSource
                  E-commerce
                                     Mobile
Why .py?
Project grows
Why .py?
Become complicated
Why .py?
Deadlines!
Why .py?
Conception suddenly changed!
Why .py?
Result
Why .py?
  Or in JAVA world        tones of X
                                           ML
            ads
         hre g
h    of t izin
  ell on
  syn chr




      modules                                   ning
       repo?                            ve rsio
                          l ibra ries
                     no
Why .py?
   A bit of PHP?     Built-in and library APIs are
                                                   a
                     disorganized mess
          c ti ons
S QL inje
                                                       core bugs



not transitive




                                                       silent e rrors
Why .py?
Python is a very new language; in fact it was released by its
designer, Guido Van Rossum, in February 1991 while working
for CWI also known as Stichting Mathematisch Centrum.


•Interpreted, interactive, object-oriented
•It incorporates modules, exceptions, dynamic data types
and classes.
•Extensible in C or C++.
•Portable across all major hardware and software platforms.
Why .py?
Zen
      Language designed for readability and productivity of the
      end-up developer

Modules
      http://pypi.python.org

Huge community
      https://github.com/languages/Python
Why .py?                                  Explicit is better than implicit.
                                             Beautiful is better than ugly.
                                                 Flat is better than nested.
                                                             Readability counts.

 class Mediator(object):
     def __init__(self):
         self.signals = {}

     def signal(self, signal_name, *args, **kwargs):
         for handler in self.signals.get(signal_name, []):
             handler(*args, **kwargs)

     def connect(self, signal_name, receiver):
         handlers = self.signals.setdefault(signal_name, [])
         handlers.append(receiver)

     def disconnect(self, signal_name, receiver):
         self.signals[signal_name].remove(receiver)




                                                               The Zen of Python
Why .py?                                  Explicit is better than implicit?
                                             Beautiful is better than ugly?
                                                 Flat is better than nested?
 class Mediator {
   private boolean slotFull = false;
   private int number;
                                                       Readability counts?
   public synchronized void storeMessage(int num) {
     while (slotFull == true) {
       try {
         wait();
       }
       catch (InterruptedException e) { }
     }
     slotFull = true;
     number = num;
     notifyAll();
   }
   public synchronized int retrieveMessage() {
     // no message to retrieve
     while (slotFull == false)
       try {
         wait();
       }
       catch (InterruptedException e) { }
     slotFull = false;
     notifyAll();
     return number;
   }
 }


                                                         Does the Java have a Zen?
Why .py?
Good old spaghetti async style
   init: function(msg, obj) {
       chrome.pageAction.show(tabId);
       me.api.authorize(function() {
           me.api.checkDoc(msg.doc,
               function(data) {
                   obj.get(msg);
                   me.api.realtime.getUpdates({
                       tabId: tabId,
                       ids: [msg.doc.id],
                       callbackOk: function(data) {
                           if (data.event == 'connected') {
                                obj.get(msg);
                           }
                           port.postMessage({_action: 'update', data: data});
                       },
                       callbackError: function(data) {
                           obj.get(msg);
                       }
                   });
               },
               function(data) {
                   console.warn('Bad document', data.responseText);
               }
           );
       });
   },
Why .py?
And how we see the same things
     @tornado.web.asynchronous
     @gen.engine
     def get(self, user_id=None):
         if user_id is not None:
             user = yield gen.Task(User.get, user_id)
             self.set_secure_cookie('uid', unicode(user._id))
             response = user.as_dict()
         else:
             count = yield gen.Task(User.objects.count)
             if not count:
                 yield gen.Task(User.create({'nickname': "John Doe"}).save)
             users = yield gen.Task(User.objects.find, None)
             response = [u.as_dict() for u in users]
         self.write(json_encode(response))
         self.finish()
Why .py?                          Need functional?

                      stripped_list = [line.strip() for line in line_list
List comprehensions                    if line != ""]



Generators            def generate_ints(N):
                          for i in range(N):
                              yield i

                      val = (yield i)



Built-ins             map(upper, ['sentence', 'fragment'])

                      [upper(s) for s in ['sentence', 'fragment']]




                      filter(is_even, range(10))

                      [x for x in range(10) if is_even(x)]



                      total = reduce(lambda a, b: (0, a[1] + b[1]), items)[1]
Why .py?              Decorators

           from functools import wraps

           def my_decorator(func):

               @wraps(func)
               def wrapper(*args, **kwargs):
                   # we can do smth with arguments
                   print “args:”, args
                   response = func(*args, **kwargs)
                   # end with the method result too
               return wrapper


           @my_decorator
           def func1(arg1):
               return "inside func1()", arg1


           >>>print func1(‘test’)

           “args: [‘test’]”
           “inside func1() test”
Why .py?               Descriptor’s magic

           An object attribute with "binding behavior", one whose
           attribute access has been overridden by methods in the
           descriptor protocol.
           class RevealAccess(object):


               def __init__(self, initval=None, name='var'):
                   self.val = initval
                   self.name = name

               def __get__(self, obj, objtype):
                   print 'Retrieving', self.name
                   return self.val

               def __set__(self, obj, val):
                   print 'Updating' , self.name
                   self.val = val

           class MyClass(object):
               x = RevealAccess(10, 'var "x"')
               y = 5

           >>> m = MyClass()
           >>> m.x
           Retrieving var "x"
           10
Why .py?                                    Metaclasses

                              Metaclasses are deeper magic than 99% of users should
                              ever worry about. If you wonder whether you need them,
                              you don't (the people who actually need them know with
                              certainty that they need them, and don't need an
                              explanation about why)
                                                                           Tim Peters

  class Singleton(type):
      instance = None
      def __call__(cls, *args, **kw):
          if cls.instance is None:
              cls.instance = super(Singleton, cls).__call__(*args, **kw)
          return cls.instance


   class Foo(object):
       __metaclass__ = Singleton
Why .py?                              Need an IDE?


 Convenient way:                     Hacker’s choices are:
 PyCharm                             VIM
 NinjaIDE                            Emacs
 WingIDE

               Hipster’s choice:
               Sublime Text (written in python, actually)
Why .py?


     But the C is much more faster!
Why .py?

       Stop! The main problem sounds like:
             the development speed,
              developer’s motivation



Have we just mentioned that the most critical parts could be written in C/C++?
The Web
The Web in the details
Fast prototyping
The Web in the details
OMG! WTF? It handles loading!
The Web in the details
The Freedom of Choice:

  •   General approach on request/response processing
  •   Reusable modules/parts
  •   Template engines
  •   ORM (RDBMS, noSQL)
  •   Caching backends
  •   Messages queue APIs (ZMQ, RabbitMQ)
  •   Localization out of the box
  •   Great documentation! Testing frameworks
  •   Debugging and profiling
The Web in the details
Batteries:

       nimnull@fox-laptop:~$ easy_install <battery name>
The Web in the details
Logic-less templates:

  •   Django Template Engine
  •   Tornado Template Engine
  •   Jinja2
  •   Mako
  •   Genshi


  • Inheritance
  • Extending
  • Compiled to the Python
The Web in the details
DB storage backends:

  • General approach of DBAPI for RDBMS
  • Arguments escaping, type checks
  • noSQL (if you expect it)

  •   SQLAlchemy (postgres, mysql, oracle, mssql)
  •   MongoKit
  •   Mongoengine
  •   CouchDbKit
The Web in the details
Asynchronous:

  • Tornado
  • twisted.web
  • gevent

  • epoll (linux), kqueue (BSD)
  • Spaghetti? No Way! (Promise/Deffered)
Success story, bro
  Pinterest                  Disqus         Quora

              Spotify       Instagram       Bitbucket

       OpenStack
                                    FriendFeed
                        Dropbox
UA Community
 http://citypy.org/           http://ua.pycon.org/

                        Kyiv
                      Kharkiv
                        Lviv
                     Donetsk
                Odessa (py.drinkups)
Questions?