Python's home: http://python.org
There are several good programming languages for creating web sites. For certain tasks, one language may be better than another. However, fluency in languages is the only way to evaluate this.
Programming is mostly learning by doing.
A programming for making long works indecipherably short
Problem: how to make abbreviations for words? Several terms have evolved from taking the first and last letter of a long word and substituting the number of letters in the middle:
#!/usr/bin/env python
import sys
import urllib2
def a8e(text):
text = text.split()
retval = []
for word in text:
if len(word) < 4:
retval.append(word)
else:
retval.append(word[0] + '%d' % (len(word) - 2) + word[-1])
return ' '.join(retval)
def main(args=sys.argv[1:]):
if len(args) == 1 and (args[0].startswith('http://')
or args[0].startswith('https://')):
text = urllib2.urlopen(args[0]).read()
else:
text = ' '.join(args)
# TODO: read from stdin if no args
print a8e(text)
if __name__ == '__main__':
main()
http://k0s.org/hg/config/file/tip/python/a8e.py
Let's walk through the a8e.py program and see what's going on:
import sys
import urllib2
import the modules you need
def a8e(text):
declare a function. this function takes exactly one argument
text = text.split()
split the passed-in string by whitespace (spaces, tabs, and newlines)
retval = []declare a variable, retval, as an empty list; this will be modified to be the value that is returned from the a8e() function
for word in text:for each word in the text ...
if len(word) < 4:
retval.append(word)
if the word has less than four characters, just append it to the list
retval
else:
retval.append(word[0] + '%d' % (len(word) - 2) + word[-1])
otherwise, take the first letter of the word, the (string of) the length of the word, and the last letter of the word and append it to the list
retval
return ' '.join(retval)make a string by joining the words in reval with a single space and return it
Run python from the command line:
> python Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
Limitations:
Some objects (instances of data types) may be changed in place. These are called mutable.
Other objects cannot be changed in place. These are called immutable.
Usually functions that operate on immutable types return a new instance of the same type.
Example: string.translate returns a new copy of the string
Note also in passing that dictionary keys must be immutable.
Importing is done with the import command:
import sys print sys.platform
You may also import individual attributes from modules:
from sys import platform print platform
Your module must exist on some component of sys.path to be importable (e.g. in the current directory)
pdb is your friend
import pdb; pdb.set_trace()
Example:
def foo(bar): return bar*bar print foo(2) # uncomment the next line to activate pdb and fix the problem! #import pdb; pdb.set_trace() print foo([2,3,4]) print foo(3)
Note: help() does not work inside a pdb (but dir() does)
virtualenv is a virtual environment to isolate python software. virtualenv allows you to isolate a development environment.
- with easy_install:
easy_install virtualenv
virtualenv is one of the few things you might want to install in your global site-packages
- in development mode:
hg clone http://bitbucket.org/ianb/virtualenv cd virtualenv python setup.py develop
Alternatively, you can run virtualenv.py directly out of the checkout directory
Usually, you'll want to make a virtualenv for a project or when trying out software
virtualenv ${project}
. ${project}/bin/activate
# on windows: ${project}/Scripts/activate.bat
For software on http://pypi.python.org:
easy_install ${package}
For software in development mode:
For this class, you'll want to easy_install paste, webob, and various other packages you might want along the way.
Python's Web Server Gateway Interface
python's Web Server Gateway Interface is a long name for the standard that software should conform to. This way, a developer may write software that can work with multiple python web servers.
WSGI provides a contract so python developers can make use of the same basic structure for request processing. This allows python code to be portable between server implementations if they implement the WSGI spec.
Basic WSGI application:
def application(environ, start_response):
text = 'hello world'
start_response("200 OK", [('Content-Type', 'text/plain'),
('Content-Length', str(len(text)))])
return [text]
Here, application is a function, but it may be anything callable (e.g. an object) that takes environ, start_response
WebOb is a simplerequest-response object. It is used by Pylons amongst other frameworks and libraries.
http://pythonpaste.org/webob/ ← read this webpage! (homework)
Getting query string parameters with WebOb:
from webob import Request
...
def __call__(self, environ, start_response):
request = Request(environ)
value = request.GET.get('key')
# for the url http://example.com/?key=elephants this will return 'elephants'
Getting POST data with WebOb:
request.POST.get('key')
Getting headers with WebOb:
request.headers.get('Content-Length')
Other functionality:
and lots more! when you have a working webapp, you can import pdb; pdb.set_trace() and use dir() to look around your request
WebOb makes web programming easy
from webob import Request, Response
def hello(environ, start_response):
request = Request(environ)
response = Response(content_type='text/plain',
body='Hello world!')
return response(environ, start_response)
from paste.httpserver import serve
serve(hello)
helloworld.py
Because of WSGI, it shouldn't (*) matter much what web server you use for testing, as your web service code should work with any WSGI server
There is an excellent comparison of WSGI server performance complete with how you would deploy a sample application (you should read!):
What is the difference between a web framework and a web server?
http://wiki.python.org/moin/WebFrameworks describes Paste as a web framework whereas here I describe it as a server. Which is it?
Web framework is a vague term and generally describes any toolkit on which you can build web sites.
#!/usr/bin/env python
import sys
import urllib2
from webob import Request, Response
def a8e(text):
text = text.split()
retval = []
for word in text:
if len(word) < 4:
retval.append(word)
else:
retval.append(word[0] + '%d' % (len(word) - 2) + word[-1])
return ' '.join(retval)
def a8eweb(environ, start_response):
request = Request(environ)
text = ' '.join(request.GET.keys())
response = Response(content_type='text/plain',
body=a8e(text))
return response(environ, start_response)
def main():
from paste.httpserver import serve
serve(a8eweb)
if __name__ == '__main__':
main()
ae8web.py
from webob import exc
# ...
def __call__(environ, start_response):
# ... do some stuff
raise exc.HTTPSeeOther(location='http://example.com/')
# XXX does not work until python 2.5!
# on older python do:
response = exc.HTTPSeeOther(location='http://example.com/')
return response(environ, start_response)
Paste is a lot of things:
But we're mostly going to use the webserver (Feel free to play with other web servers! Paste isn't commonly used in production)
paste .ini files tell you how to assemble a website from WSGI applications
#!/usr/bin/env paster [DEFAULT] debug = true email_to = jhammel@mozilla.com smtp_server = localhost error_email_from = paste@localhost [server:main] use = egg:Paste#http host = 0.0.0.0 port = 7654 [composite:main] use = egg:Paste#urlmap / = hello set debug = false [app:hello] paste.app_factory = hello.factory:factoryhello.ini
Breaking this down:
There are several sections to this .ini file:
#!/usr/bin/env paster ← she-bang to run this file with
[DEFAULT] debug = true email_to = jhammel@mozilla.com smtp_server = localhost error_email_from = paste@localhost
[server:main] use = egg:Paste#http ← use the Paste web server host = 0.0.0.0 ← serve on this IP address (the local machine) port = 7654 ← serve on port 7654
[composite:main] use = egg:Paste#urlmap ← use this to map URLS / = hello ← map the root use to the hello application
set debug = false ← don't use debug in production!
[app:hello] paste.app_factory = hello.factory:factory ← factory to create the hello application
paste factories tell how to compose a WSGI application
In order to use a paste factory, it must be available on your path