PenPen

The typing penguin

Python developer, Linux administrator and MacOS user from Russia.

Based on theme by Andy Taylor

 

Multi site system on single django project with uwsgi

Yesterday I’ve set up an interesting uwsgi installation, which can serve multiple sites from single django project. Here is uWSGI Upstart script for ubuntu server:


description "uWSGI starter"

start on (local-filesystems
and runlevel [2345])
stop on runlevel [016]

respawn

exec /usr/local/bin/uwsgi --uid penpen \
-s 127.0.0.1:9010 -M -p 2 --reload-os-env \
--logto /home/penpen/logs/biribiri/uwsgi_log \
-H /home/penpen/biribiri/virtualenv \
--pythonpath /home/penpen --vhost --vhost-host

This script uses uWSGI virtual hosting mode, which allows multiple wsgi apps in single interpreter (unlike emperor mode, which uses interpreter per app (or site)).
It is necessary to use “—reload-os-env” option, which passes environment variable through UWSGI_SETENV parameter. In this installation nginx passes current site name in uwsgi, which loads settings from module named as biribiri.hosts.SITE_NAME.
For production use, it would be a nice idea to check if file exists and use default settings for non-existant sites.
I use DJANGO_HOST instead of DJANGO_SETTINGS_MODULE because in current installation it overrides somewhere.
Nginx config:


server {
	listen 80 default;
	server_name biribiri;
	root /home/penpen/biribiri;

	location / {
		uwsgi_pass 127.0.0.1:9010;
		uwsgi_param UWSGI_MODULE biribiri.production.wsgi;
		uwsgi_param UWSGI_SETENV DJANGO_HOST=biribiri.hosts.$http_host;
		include uwsgi_params;	
	}
}

wsgi.py connector for django (in biribiri.production.wsgi):


import os
import sys

path = '/home/penpen/biribiri'

if path not in sys.path:
    sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE'] = os.environ['DJANGO_HOST'].replace('.ru', '')

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

In the above code snippet we are going to remove TLD from site name, because python modules don’t allow dot in their names.

Publishedin

One of my friends told me about good service for bloggers. Here is - http://publishedin.com/

Leaf

I’ve just released leaf 0.4. This is simple python library for html parsing.

GitHub

Python packages

Ugly unicode text

A couple of days ago, I worked with an ugly unicode text, kind of like this:

ⒶⓀⓋⓉⒺ
b̼̘̬ͭ͂̈́̀l͇͉̱͚̲̗̗͞a̱̭̬͎͉̤ͨ͂̌̑̓͂͐h̬̯̻̩͗ͩͯḅ̢̬͕͈̥̅̌͆̔̉ͅḽ̘̖̼͚́͒̈́̏͌̃͟ ͎̮̫̍ͫ̽͐͋ͤ͂a̜͔̩͇̩̪͐̍̐̃ͤ͑ ̦̌ḧ̙̝͓̜͕̝̈́ͅb̛̞͔̽̃̍ͪla̘̠͖͍̣͙̝͌ͪ͒̃ͯ ͗͛̆͊.̛̭̜̞̲͓̯ͧ̅ĥ͂͑/̢̊/̠̘͖͖̖̺̯

And I need to get a normal text from this shit, because MySQL has weird unicode support. So I made these simple functions for cleaning up unicode text:

def strip_accents(s):
    """ Strip accents from a string """
    result = []
    for char in s:
		# Pass these symbols without processing
        if char in [u'й', u'Й', u'\n']: 
            result.append(char)
            continue
        for c in unicodedata.normalize('NFD', char):
            if unicodedata.category(c) == 'Mn':
                continue
            result.append(c)
    return ''.join(result)
def strip_symbols(s):
    """ Strip ugly unicode symbols from a string """
    result = []
    for char in s:
		# Pass these symbols without processing
        if char in [u'й', u'Й', u'\n']:
            result.append(char)
            continue
        for c in unicodedata.normalize('NFKC', char):
            if unicodedata.category(c) == 'Zs':
                result.append(u' ')
                continue
            if unicodedata.category(c) not in ['So', 'Mn', 
                             'Lo', 'Cn', 'Co', 'Cf', 'Cc']:
                result.append(c)
    return u"".join(result)

Timestamps in Python

Sometimes you need to use unix timestamp in Python for data exchange with external application (e.g. PunBB stores date as timestamp). Unfortunately Python doesn’t have a built-in function for that. 
Here are some functions for that from my utils.py.

Convert datetime.datetime object to unix timestamp:

def timestamp(datetime_obj):
    """ Convert datetime object to timestamp """
    if type(datetime_obj) is datetime.datetime:
        return int(time.mktime(datetime_obj.timetuple()))
    else:
        return int(datetime_obj)

Convert unix timestamp to datetime.datetime object:

def from_timestamp(timestamp):
    """ Convert timestamp to datetime object"""
    return datetime.datetime.fromtimestamp(timestamp)

Return current unix timestamp:

def timestamp_now():
    """ Return current unix timestamp """
    return timestamp(datetime.datetime.now())

Enjoy!