Caleb Madrigal

Programming, Hacking, Math, and Art

 

Calling synchronous code from asyncio

I recently needed to call some synchronous code from asyncio. Thankfully, asyncio provides the run_in_executor function, which runs the specified function in a different thread. Here is an example of using it:

call_sync_code.py download
import asyncio
import time
from urllib.request import urlopen

@asyncio.coroutine
def count_to_10():
    for i in range(11):
        print("Counter: {}".format(i))
        yield from asyncio.sleep(.5)

def get_page_len(url):
    # This is the blocking sleep (not the async-friendly one)
    time.sleep(2)
    page = urlopen(url).read()
    return len(page)

@asyncio.coroutine
def run_get_page_len():
   loop = asyncio.get_event_loop()

   future1 = loop.run_in_executor(None, get_page_len, 'http://calebmadrigal.com')

   #data1 = yield from future1
   return future1

@asyncio.coroutine
def print_data_size():
   data = yield from run_get_page_len()
   print("Data size: {}".format(data))


loop = asyncio.get_event_loop()
tasks = [
    asyncio.async(count_to_10()),
    asyncio.async(print_data_size ...

Algorithms in Python

I recently decided to brush up on my algorithms and data structures by writing them in Python. Though these are not optimized, they could be helpful for reference. Here is the Github repo: https://github.com/calebmadrigal/algorithms-in-python.

A some of the algorithms included:

Recursion with asyncio

Recursion is awesome, but has the downside of growing the stack, which can limit its usefulness. Some languages like Scheme, however, have Tail-call optimization, which lets programmers write Tail-recursive functions that don't grow the call stack. Python does not have Tail-call optimization (TCO), but with asyncio, we can have something like Tail-call optimization. Basically, this method uses the asyncio event loop like a trampoline function.

Example:

tail_recursion_with_asyncio.py download
import asyncio

# Tail-recursive factorial using asyncio event loop as a trampoline to
# keep the stack from growing.
@asyncio.coroutine
def factorial(n, callback, acc=1):
    if n == 0:
        callback(acc)
    else:
        asyncio.async(factorial(n-1, callback, acc*n)) # async -> ensure_future in Python 3.4.4

def done_callback(result):
    print("Result: {}".format(result))
    loop = asyncio.get_event_loop()
    loop.stop ...

Display List as Table in IPython Notebook

IPython Notebook provides hook methods like _repr_html_ which can be defined by Python objects to allow richer representations. Here's an example:

In [1]:
class ListTable(list):
    """ Overridden list class which takes a 2-dimensional list of 
        the form [[1,2,3],[4,5,6]], and renders an HTML Table in 
        IPython Notebook. """
    
    def _repr_html_(self):
        html = ["<table>"]
        for row in self:
            html.append("<tr>")
            
            for col in row:
                html.append("<td>{0}</td>".format(col))
            
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)
In [23]:
import random
table = ListTable()
table.append(['x', 'y', 'x-y', '(x-y)^2'])
for i in xrange(7):
    x = random.uniform(0, 10)
    y = random.uniform(0, 10)
    table.append([x, y, x-y, (x-y)**2])
table
Out[23]:
xyx-y(x-y ...

How To Draw Lines With Matplotlib

Simple example to show how to draw lines with Matplotlib (in IPython Notebook).

ipython notebook --pylab inline

In [5]:
import matplotlib.lines as lines
fig, ax = plt.subplots()

fig.set_size_inches(6,6)          # Make graph square
scatter([-0.1],[-0.1],s=0.01)     # Move graph window a little left and down

line1 = [(0,0), (1,0)]
line2 = [(0,0), (0,1)]

# Note that the Line2D takes a list of x values and a list of y values,
# not 2 points as one might expect.  So we have to convert our points
# an x-list and a y-list.
(line1_xs, line1_ys) = zip(*line1)
(line2_xs, line2_ys) = zip(*line2)

ax.add_line(Line2D(line1_xs, line1_ys, linewidth=2, color='blue'))
ax.add_line(Line2D(line2_xs, line2_ys, linewidth=2, color='red'))
plot()
show()
Read On ↵

Opposite of zip function in Python

Is there a way to do the opposite of what the zip() function does? It turns out, there is - the zip() function with list unpacking...

Normal zip() usage

In [5]:
x = [1,2,3,4,5]
y = [10,20,30,40,50]
points = zip(x,y)
points
Out[5]:
[(1, 10), (2, 20), (3, 30), (4, 40), (5, 50)]

Reverse of normal zip() with list unpacking

By using list unpacking (by using the asterisk before the list), zip can effectively act in reverse...

In [6]:
zip(*points)
Out[6]:
[(1, 2, 3, 4, 5), (10, 20, 30, 40, 50)]

Example of usefulness

In [19]:
import random
rand = lambda: random.gauss(mu=1, sigma=1)
points = [(rand(), rand()) for i in xrange(1000)]

# Make the graph square
fig = plt ...

Wordpress to Pelican Reasons

I recently migrated my blog from Wordpress to Pelican. Pelican is a static-site generating blog system which is written in Python and uses Jinja2 for templating. I'll probably do a post about the migration process later, but for now, I'll just give my reasons for moving to Pelican...

Data Longevity

I didn't want my blog data stored in a database; I vastly prefer it being stored in version-controlled Markdown format.

Markdown

  • I wanted to write blog posts in Markdown (which is possible in Wordpress, but Wordpress isn't designed to use Markdown).
  • I also get to use vim to write my blog posts now, which is much nicer than the Wordpress editor.

Language

  • I hate PHP, but love Python. It worried me that my blog ...

IPython Notebook on a VPS

Overview

This is a guide to set up IPython Notebook on a Server - specifically, on a DigitalOcean VPS. This will allow you to access your iPython Notebooks from anywhere.

Overview of Steps:

  • Set up a domain name
  • Get a VPS
  • Install IPython Notebook (and all dependencies)
  • Configure IPython Notebook to run in a server mode
  • Add SSL
  • Make IPython Notebook start automatically

Create a domain

Go to http://freedns.afraid.org and click "Setup an account here" Go through the signup form Click on the activation link they send to your email This will bring you back to their site; Click the link you see there called "Add a subdomain" Here is how I filled out the form:

Create Domain

Notes:

  • Leave the Destination alone for now, and leave the ...

Big graphs in IPython Notebook

I've been doing a good bit of graphing in IPython Notebook recently, and I often wanted to make the graphs larger. I also often wanted to label the graph axes. So I wrote this simple function and have been using it a lot.

# Graphing helper function
def setup_graph(title='', x_label='', y_label='', fig_size=None):
    fig = plt.figure()
    if fig_size != None:
        fig.set_size_inches(fig_size[0], fig_size[1])
    ax = fig.add_subplot(111)
    ax.set_title(title)
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)

Here's a demo of using it...

In [27]:
x = linspace(0, 2 * pi, 1000)
y = 5 * sin(1 * 2*pi*x) + 4 * sin(2 * 2*pi*x)

Without setup_graph()

In [24]:
_ = plot(x, y)
Read On ↵

How to graph with IPython Notebook

IPython Notebook / Matplotlib / Pylab / Numpy is great for graphing (among other things). Below is a simple demo of how to graph with it.

To run IPython Notebook, use this command: ipython notebook --pylab inline

Here's a screenshot:

IPython Notebook Example

Here's an embedded IPython Notebook showing a slightly easier way:

In [5]:
x = linspace(0, 2*pi, 42)
f1 = 5 * sin(x)
f2 = 2 * sin(2*x)
f3 = 1 * sin(3*x)
plot(x, f1)
plot(x, f2, 'ro')
plot(x, f3, 'g--')
show()
Read On ↵

First look at Pylab/Matplotlib

Since I've been getting into Machine Learning/Artificial Intelligence recently, I've been looking at various computing environments recently. Some of the contenders are:

  • MATLAB - The traditional software stack for doing machine learning and statistical analysis
  • GNU Octave - An open-source MATLAB clone.
  • R - An open source clone of a statistical computing environment called S.
  • Julia - A language for doing statistical analysis. The goals are to compete with Matlab and R.
  • Matplotlib/Pylab/SciPy/NumPy - see below

Of these, I've tried Octave and Matplotlib. Matplotlib/Pylab is the software stack consisting of:

  • IPython - an interactive REPL for Python with things like tab completion
  • Matplotlib - a graphical plotting library
  • NumPy - a matrix library
  • SciPy - a collection of scientific and mathematical algorithms

I've only played with Matplotlib/Pylab ...

Tail call optimization in Python

Since I've been getting into functional programming more recently, the fact that Python doesn't do tail-call optimization has been bothering me. So I did a bit of searching, and found this gem: Tail Call Optimization Decorator.

Here is a snippet from it:

import sys

class TailRecurseException:
  def __init__(self, args, kwargs):
    self.args = args
    self.kwargs = kwargs

def tail_call_optimized(g):
  """
  This function decorates a function with tail call
  optimization. It does this by throwing an exception
  if it is it's own grandparent, and catching such
  exceptions to fake the tail call optimization.

  This function fails if the decorated
  function recurses in a non-tail context.
  """
  def func(*args, **kwargs):
    f = sys._getframe()
    if f.f_back and f.f_back.f_back \
        and f.f_back.f_back.f_code == f.f_code ...

Standard Deviation in Python

I just wanted to go through the process of calculating standard deviation today, and this is how I did it in Python. Python makes such a nice calculator :)

>>> s = [2,4,4,4,5,5,7,9]
>>> def average(s): return sum(s) * 1.0 / len(s)
... 
>>> avg = average(s)
>>> avg
5.0
>>> variance = map(lambda x: (x - avg)**2, s)
>>> variance
[9.0, 1.0, 1.0, 1.0, 0.0, 0.0, 4.0, 16.0]
>>> average(variance)
4.0
>>> import math
>>> standard_deviation = math.sqrt(average(variance))
>>> standard_deviation
2.0
>>>

Django on Hostmonster

I just finished going through the process of installing and configuring Django (with FastCGI) on Hostmonster's Shared hosting. It was more painful than I expected, so I decided write a post about how I got it working...

First, I wanted to create a subdomain which would host my django stuff. In order to do this, I created a subdomain using the cPanel (the item is called "Subdomains"). This created the directory and a basic .htaccess file (along with a few error pages).

I then went through the basic processes described on these pages:

When I finished these guides, I kept getting a 500 error. I eventually found that I can access the error log ...

Consuming web service in Python with SUDS

import datetime
from suds.client import Client
url = "http://localhost:9080/dataplanws/DataPlanWebService/WEB-INF/wsdl/DataPlanWebService.wsdl"
client = Client(url)
print client.service.hello("Caleb")