Draft
This page is not complete.

Python is a widely used, general-purpose, interpreted scripting language. It is available on a broad range of platforms, including Windows, Linux, and Mac OS X. Python helps you work quickly and integrate systems effectively, and it encourages programmers to program without boilerplate (prepared) code.

In this series of tutorials, you'll learn to use the basic building blocks of Python 3. After getting a taste for the language, you'll learn how to build Sked, a simple web application to keep track of a conference schedule

Learn Python basics

Bring Python to the Web

  • Setting the stage
  • The simple web application
  • Database basics
  • Python on the client
    • Accessing the DOM
    • Using JavaScript libraries
    • Sharing code between client and server

Python on the client

There are several ways to run Python in a browser.

  1. Python can be precompiled to JavaScript. In that case only the resulting JavaScript code is loaded with the page, unless source level debugging is required.
  2. Python can be executed by an interpreter written in JavaScript that runs in the browser. In that case the Python sourcecode and the interpreter are loaded with the page.
  3. Python bytecode can be run by a virtual machine that resides  in the browser. In that case the Python bytecode and the virtual machine are  loaded with the page.

The examples below use the first approach and a tool called Transcrypt.

Accessing the DOM

Accessing the DOM is done in the same way as would be the case when programming in JavaScript. An example of a simple hello.py application.

    <script src="__javascript__/hello.js"></script>
    <h2>Hello demo</h2>
    
    <p>
    <div id = "greet">...</div>
    <button onclick="hello.solarSystem.greet ()">Click me repeatedly!</button>
    
    <p>
    <div id = "explain">...</div>
    <button onclick="hello.solarSystem.explain ()">And click me repeatedly too!</button>

 

    from itertools import chain
    
    class SolarSystem:
        planets = [list (chain (planet, (index + 1,))) for index, planet in enumerate ((
            ('Mercury', 'hot', 2240),
            ('Venus', 'sulphurous', 6052),
            ('Earth', 'fertile', 6378),
            ('Mars', 'reddish', 3397),
            ('Jupiter', 'stormy', 71492),
            ('Saturn', 'ringed', 60268),
            ('Uranus', 'cold', 25559),
            ('Neptune', 'very cold', 24766) 
        ))]
        
        lines = (
            '{} is a {} planet',
            'The radius of {} is {} km',
            '{} is planet nr. {} counting from the sun'
        )
        
        def __init__ (self):
            self.lineIndex = 0
        
        def greet (self):
            self.planet = self.planets [int (Math.random () * len (self.planets))]
            document.getElementById ('greet') .innerHTML = 'Hello {}'.format (self.planet [0])
            self.explain ()
            
        def explain (self):
            document.getElementById ('explain').innerHTML = (
                self.lines [self.lineIndex] .format (self.planet [0], self.planet [self.lineIndex + 1])
            )
            self.lineIndex = (self.lineIndex + 1) % 3
            
    solarSystem = SolarSystem ()
    

 

Using JavaScript libraries

JavaScript libraries can either be used directly from the Python source code or encapsulated in a Python module which is then imported in the application program. Below is an example of direct use of the D3.js library in an application d3js_demo.py:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.1/d3.min.js"></script>
    <script src="__javascript__/d3js_demo.js"; charset="UTF-8"></script>

 

    class Spawn:
        def __init__ (self, width, height):
            self.width, self.height, self.spacing = self.fill = width, height, 100, d3.scale.category20 ()
    
            self.svg = d3.select ('body'
            ) .append ('svg'
            ) .attr ('width', self.width
            ) .attr ('height', self.height
            ) .on ('mousemove', self.mousemove
            ) .on ('mousedown', self.mousedown)
            
            self.svg.append ('rect'
            ) .attr ('width', self.width
            ) .attr ('height', self.height)
    
            self.cursor = self.svg.append ('circle'
            ) .attr ('r', self.spacing
            ) .attr ('transform', 'translate ({}, {})' .format (self.width / 2, self.height / 2)
            ) .attr ('class', 'cursor')
    
            self.force = d3.layout.force (
            ) .size ([self.width, self.height]
            ) .nodes ([{}]
            ) .linkDistance (self.spacing
            ) .charge (-1000
            ) .on ('tick', self.tick)       
    
            self.nodes, self.links, self.node, self.link = self.force.nodes (), self.force.links (), self.svg.selectAll ('.node'), self.svg.selectAll ('.link')
            
            self.restart ()
            
        def mousemove (self):
            self.cursor.attr ('transform', 'translate (' + d3.mouse (self.svg.node ()) + ')')
    
        def mousedown (self):
            def pushLink (target):
                x, y = target.x - node.x, target.y - node.y
                if Math.sqrt (x * x + y * y) < self.spacing:
                    spawn.links.push ({'source': node, 'target': target})
                    
            point = d3.mouse (self.svg.node ())
            node = {'x': point [0], 'y': point [1]}
            self.nodes.push (node)
            self.nodes.forEach (pushLink)
            self.restart ()     
                
        def tick (self):
            self.link.attr ('x1', lambda d: d.source.x
            ) .attr ('y1', lambda d: d.source.y
            ) .attr ('x2', lambda d: d.target.x
            ) .attr ('y2', lambda d: d.target.y)
                
            self.node.attr ('cx', lambda d: d.x
            ) .attr ('cy', lambda d: d.y)
    
        def restart (self):
            self.link = self.link.data (self.links)
            
            self.link.enter (
            ) .insert ('line', '.node'
            ) .attr('class', 'link')
    
            self.node = self.node.data (self.nodes)
                
            self.node.enter (
            ) .insert ('circle', '.cursor'
            ) .attr ('class', 'node'
            ) .attr ('r', 7
            ) .call (self.force.drag)
    
            self.force.start ()
    
    spawn = Spawn (window.innerWidth, window.innerHeight)

Sharing code between client and server

It is possible to share Python modules between client and server or desktop application. For this to work, the shared modules must be pure Python modules, not use any C code directly or indirectly.

An example of code that both runs both in a browser and on a desktop application is the following:

from turtle import *
from random import *

speed (0)

colors = ('gray', 'green', 'red', 'white', 'blue', 'yellow')
delta = 8
threshold = 100
color ('black', 'black')

def maybe (bias = None):
    return choice ([False, True, bias, bias] if bias != None else [False, True])    

def between (a, b):
    return a + (0.2 + 0.3 * random ()) * (b - a)

recentColors = ['black', 'black']
def originalColor ():
    global recentColors
    while True:
        result = choice (colors)
        if result == 'white' or not result in recentColors:
            recentColors = [result, recentColors [0]]
            print (result, end = ' ')
            return result
    
def rect (xMin, yMin, xMax, yMax):
    for aColor in ('black', originalColor ()):
        color (aColor, aColor)
        
        up ()
        goto (xMin, yMin)
        down ()
        
        begin_fill ()
        goto (xMax, yMin)
        goto (xMax, yMax)
        goto (xMin, yMax)
        goto (xMin, yMin)
        end_fill ()
        
        xMin += delta
        yMin += delta
        xMax -= delta
        yMax -= delta
    
def draw (xMin = -250, yMin = -300, xMax = 250, yMax = 300):
    if xMax - xMin > threshold and yMax - yMin > threshold:
        if maybe (xMax - xMin > yMax - yMin):
            xMid = between (xMin, xMax)
            if maybe ():
                draw (xMin, yMin, xMid, yMax)
                rect (xMid, yMin, xMax, yMax)
            else:
                rect (xMin, yMin, xMid, yMax)
                draw (xMid, yMin, xMax, yMax)
        else:
            yMid = between (yMin, yMax)
            if maybe ():
                draw (xMin, yMin, xMax, yMid)
                rect (xMin, yMid, xMax, yMax)
            else:
                rect (xMin, yMin, xMax, yMid)
                draw (xMin, yMid, xMax, yMax)
    else:
        rect (xMin, yMin, xMax, yMax)
        ontimer (lambda: (print (), clear (), draw ()), 2000)
draw ()
done ()     

Note that on the desktop the modules random and turtle will use C code, whereas in the browser pure Python versions of these modules will be loaded. This happens transparently.

Old articles

Document Tags and Contributors

Last updated by: JdeH,