This is the README file for bzero, a blogging tool.

Copyright (C) 2002-03, Phillip Pearson
All rights reserved.


bzero is free for personal use.

There is NO WARRANTY. It still has bugs: by using this code you accept that it is not perfect, and will quite likely do strange things from time to time.

[ That said, it seems reasonably stable at the moment and has never lost even a single one of my blog posts :-) ]

bzero's future is still being decided. It may end up as part of a commercial package, or it may not. Whatever happens, it's likely that the command-line version [this one] will remain free for personal use, however, so don't let the commercialness put you off.

If you have any suggestions, please get in touch. New ideas are always welcome!


bzero includes Mark Nottingham's RSS parser (b0lib/, available from and released under the following license:


Thanks, Mark.

bzero includes Brett Cannon's pure Python version of strptime (b0lib/, available from the Python cookbook:

Thanks, Brett.

bzero includes Gonēalo Rodrigues's date manipulation code (b0lib/, available from the Python cookbook:

Thanks, Gonēalo.


bzero is a blogging tool written entirely in Python, with the philosophy that using the system (OS / language) to do as much of the work for us as possible is a Good Thing:

For an example of what bzero is capable of, take a look at the weblog 'Second p0st'.

I put a bzero blog on every public community server I can find. So far there are eight or so. See if you can find them all ;-)


First install Python 2.2. If you want to get 'width' and 'height' tags in automatically-posted images, you also need to install the Python Imaging Library.

Under Debian GNU/Linux, you can get them both with this:

apt-get install python2.2 python2.2-xmlbase python2.2-imaging

On Windows, you need to download and run the Python install package from, and the PIL installer from

Now you can install bzero.


Untar the archive into a temporary directory, and as root, run in that directory.

# tar -vzxf bzero-0.xx.tar.gz
# cd bzero-0.xx/
# python install

Now if you are running Linux, the library files will be installed in /usr/lib/python2.2/b0lib, support files will be in /usr/share/bzero, and /usr/bin/bzero will be the main executable. On Unices that use /usr/local (e.g. FreeBSD), the files will go in /usr/local/lib/python2.2/b0lib, and so on.

If you don't want to install it as root, just unpack it in a user directory and run from there. You might need to set the environment variable 'BZERO_LIB' to point to the directory containing the files for it to run.


Unpack the archive somewhere.

Install by running

C:\temp\bzero-0.19-py2.3> c:\python23\python install

Run bzero by typing 'python c:\python23\scripts\bzero' (change 'c:\python23' to the path to your Python installation, e.g. use 'python d:\lib\python\scripts\bzero' if you have installed it in d:\lib\python instead of c:\python23 -- see the usage examples below).

If that doesn't work, you may need to set some environment variables before running it. Three are used: BZERO_LIB, EDITOR and HOME. BZERO_LIB should point to your bzero installation directory, EDITOR should point to your editor, and HOME should be your home directory.

For me, that would be:

set BZERO_LIB=c:\bzero
set EDITOR=c:\windows\system32\notepad.exe
set HOME=c:\documents and settings\phil

After unpacking

Type 'bzero' ('python c:\python2.3\scripts\bzero' on Windows) to get some instructions on how to use it.


Once you've created a new blog (read the instructions that you get when you run 'bzero'), post by running:

bzero post blogname

This will open your editor (defined by the EDITOR or VISUAL environment variable, or /etc/alternatives/editor, or notepad.exe on Windows) with a blank post template.

Here's an example post.

#date (2003, 11, 5, 22, 2, 14, 2, 309, 0)
%topics The Matrix, Movies, News Aggregators
%ite thematrix, social_software
%title Haven't seen Matrix Revolutions yet
I'm scared to open my aggregator today, after <i>almost</i> reading a Matrix Revolutions spoiler. I'm not reading any blogs until I get to see the movie! Heh. Maybe I'll make it Friday or Saturday night.

The #date at the start is the timestamp - ignore this (don't change it). The %topics line specifies which topics the post appears in. This particular post will have three links under it when it is posted, linking to the "The Matrix", "Movies" and "News Aggregators" topics. The topics are all summarised in your contents.html file. The %ite line specifies which Topic Exchange topics the post appears in. This one will show up in the thematrix and social_software channels.

NB: Line breaks will automatically be inserted when you put line feeds in the post text. If you don't like this (and want to code your HTML yourself), put %format html at the top of your post, and no auto-formatting will occur.

Once you have finished editing, save the post. If using notepad.exe on Windows and you have used any multi-byte (e.g. Chinese, Japanese) characters, you may need to use Save As and change the file format to UTF-8.

Now publish the blog to your community server:

bzero send blogname

The following will bring up the most recent post in your editor:

bzero editlast blogname

The following will bring up the post two posts back from that one:

bzero editlast blogname -2

If you want to get information about your recent posts, try this:

bzero recent blogname

This will give you the last 100 posts:

bzero recent blogname 100

If you want to find the permalink of the last post, do this:

bzero url blogname

You can get the 5th-last post like this:

bzero url blogname -5

Writing longer 'stories' or 'articles'

You can create standalone web pages in bzero if you like. These are stored apart from the blog posts, and are rendered slightly differently. Any file with a .txt extension that you create under ~/.bzero/blogname/site/ will be rendered with the '' template and uploaded to your website.

You can create a story automatically like this:

bzero story blogname storyname

This will bring your text editor up with a template that you can edit. Fill in the title, then write your story underneath.

If you prefer to do it manually, create a file under the site directory and put the following two lines at the start:

%title title
%date dddd-dd-dd

(Replace title and dddd-dd-dd with your title and date.)

To mimic Radio's 'story' functionality, create a directory called ~/.bzero/blogname/site/stories/ and add .txt files there. Automatic indices will come later.

Note: Don't create site/index.txt, or it will conflict with your blog main page.

Posting files

You can post general files (not blog posts or articles) to the server if you like.

Any files that are stored in the ~/.bzero/blogname/extra/ folder will be uploaded directly to your website without rendering.

You can do it automatically like this:

bzero dropfile blogname filename

This will copy the file into a subdirectory of the the extra directory (named with today's date) and give you the URL.

Posting images

To post an image, simply create an <img ...> tag in a post that links to the image you want to post.

If the image is not already on a web server somewhere, the following will save a copy to be published along with your weblog HTML and open up a new post containing a pre-made <img ...> tag linking to the new image.

bzero postimg blogname (image)


bzero postimg foobar my_picture.jpg

This will post 'my_picture.jpg' to the blog called 'foobar'.

Note: You need to have the Python Imaging Library installed for this to work properly (and generate 'width' and 'height' attributes in your HTML).

Posting by e-mail

bzero can check an e-mail account for you and post messages to your blog. You need to tell it about your mail account, and make up a 'secret', which it will use to verify that messages are really coming from you. (Otherwise anybody who knows your e-mail address would be able to post to your blog).

To set this up, run

bzero setup blogname

and edit the <email ...> part, setting the attributes as follows:

server: The hostname of your mail (POP3) server, e.g.

login: Your mail login name, e.g. "phil".

password: Your mail password.

secret: The aforementioned 'secret' that tells bzero to post this message to your weblog.

Now, to check your mail and make posts out of any messages that have the secret value in their subject lines:

bzero checkmail blogname

You will need to publish the blog before any messages will show up there:

bzero send blogname

Restoring a backed up weblog

If you have backed up your weblog in XML format, you can import the backup into a new bzero weblog. This is useful if you want to switch blogging packages (moving from Radio to bzero, for example) or if your hard disk has died and all your posts are gone.

To make the backup in the first place, see 'Making an XML backup' below, or how to do it in Radio UserLand if you are importing a Radio weblog.

To import, run:

bzero import blogname url-to-files.xml

For example:

bzero import foobar

This will download all the backed-up data and use it to recreate the ~/.bzero/blogname/data directory. If that directory already exists, it will be moved out of the way. (You might want to create a new weblog to experiment with - importing over the top of an existing blog will work, but may not be what you were intending).

Making an XML backup

You can archive your weblog in XML format (currently RSS 2.0):

bzero archive blogname
bzero send blogname

To browse the archive, either use BlogGazer (from Myelin) or BlogBrowser (from Brent Simmons).



Mac OS X


Making a text backup

You can archive your weblog in a really easy to parse text format too:

bzero fsdump blogname path-to-output

Warning: this will probably stomp all over anything already in the path-to-output. It will create a hierarchy of directories, sort of like those in the ~/.bzero/blogname/data location, except with a directory rather than a file for each post, and with all the attributes of each post being stored as separate files within that directory. Try it to see what I'm talking about :-)

This sort of thing is probably very handy if you want to export data to different blogging tools. I had blosxom in mind when I wrote it.

Pushing your pages to a search engine

If you are sending your weblog to a relatively recent version of Python Community Server, e.g. the ones on or, your posts will automatically be sent and indexed. This used to be a manual process -- but no more!

Putting metadata in your HTML header

If you want to participate in projects like GeoURL, you will want to add META tags to the HTML header on your blog's index page. You can do this by putting the extra headers in a file called ~/.bzero/blogname/extraheaders.html.

Here's what the GeoURL entry for Second p0st looks like:

<meta name="ICBM" content="-43.5298,172.6306" />

Putting extra HTML at the bottom of your blog

If you want to participate in projects like BlogShares, you will want to be able to link to various places in your blog main page. You can add HTML to the bottom of your page by creating a file called ~/.bzero/blogname/extrabase.html and putting the HTML in there.

Here's what the BlogShares code on the PyCS devlog looks like:

<a href=""><img src="" alt="Listed on BlogShares" width="117" height="23"/></a>

Publishing without pinging

If you don't want to ping and your community server when you push your updates to your blog, you can tell bzero not to do that like this:

bzero send blogname noping

This will send blog blogname to the server but won't send any pings. This will speed things up a little.

Built-in web server

You can serve your blog directly from bzero if you feel like it. It's not all that clever a web server, but it might be good for testing before you send your blog out to the real world.

bzero serve blogname port


bzero serve myblog 80

That will start a web server on port 80 to serve your weblog. Note that on UNIX you need to have root privileges to do this. On Windows it should work fine (as long as you don't already have a web server running on the same machine).


When you create a new blog, a subdirectory of ~/.bzero (C:\Documents and Settings\(username)\.bzero on Windows) is created to hold the associated data (posts, rendered HTML, etc). You can customise various things by editing files in that directory.


To customise your page templates, edit the files in the ~/.bzero/blogname/templates/ directory. is your homepage template, and is your RSS feed template. Both files are just Python code, so you can do anything there that you usually can in Python.


To customise your blogroll, edit ~/.bzero/blogname/ It is also Python code, so be careful with what you put in there. If you follow the existing examples, you should be fine.

Note that you are not required to leave in the links that lead back to bzero and Myelin, but they are always appreciated ;-)

Post template

The default post template (with title 'New Post' and content 'Enter text here') is fairly plain and will almost certainly not suit your style. If you have a better idea of what you want to appear by default, save it as ~/.bzero/blogname/defaultPost.txt and it will be used instead.


Database errors

bzero doesn't use a database to store post information, but it does use a dbm file to keep track of which files it has sent to the community server. If you get odd errors like this:

raise error, "db type could not be determined"
anydbm.error: db type could not be determined
Exception exceptions.AttributeError: "Publisher instance has no attribute 'state'" in <bound method r.__del__ of <b0lib.publish.Publisher instance at 0x00AC0A80>> ignored

Try deleting the directory.dbm file (inside .bzero somewhere). It doesn't store any critical information, just the timestamps of the files on the server. As such, deleting it will trigger a full upstream, so be prepared for the next bzero send to take a while.

Thanks to Doug for pointing this out.

XML-RPC errors

If you get a whole lot of junk ending with a line looking like:

xml.parsers.expat.ExpatError: junk after document element: line 2, column 0

... then something to do with the communication with the server is screwing up. To debug this, set the BZERO_DEBUG environment variable, and bzero will show you the contents of all XML-RPC messages it sends to the server.

export BZERO_DEBUG=1
bzero etc

If you are talking to a phpStorageSystem server, it is probably returning PHP errors in the response before the XML. Contact your server administrator to get it fixed.

Any questions?

Get in touch!

Thanks for helping test bzero :-)