Tag Archives: blogging about blogging

Better Blogging with Jupyter Notebooks on WordPress.com

When I discovered Jupyter notebooks a few years ago I instantly recognized their potential as a technical blogging tool. Jupyter notebooks support mixtures of text, mathematics, program code, and graphics in a completely interactive environment. It’s easy to convert notebook JSON .ipynb files to markdown, \LaTeX, and HTML so it’s not a big leap to use Jupyter as a super-editor for blog posts with heavy doses of code, mathematics, and graphics.

I converted a few simple notebooks into HTML and tried loading them to my WordPress.com blog; the results did not amuse me! Raw notebook HTML is not suitable for WordPress.com.

WordPress.com imposes some serious constraints on low cost and free blogs. You cannot:

  1. Use arbitrary JavaScript.
  2. Import standalone CSS styles.
  3. Use non-standard plugins.

By setting up your own WordPress.org site or upgrading your WordPress.com account you can shed these limitations. I’ve considered both options but there’s just something about software vendors teasing users with basic features while nagging them to spend more on upgrades that gets my goat. I’m used to such abuse from the likes of Adobe and would advise WordPress.com to dial back upgrade nagging.

Fortunately, it’s not necessary to upgrade your WordPress.com account to make excellent use of Jupyter notebooks. With a few simple notebook file hacks, you can compose in Jupyter and post to WordPress.com

Hack #1: nb2wp

Benny Prijono has created a handy Python program nb2wp that converts Jupyter notebooks to WordPress.com oriented HTML. nb2wp uses BeautifulSoup, (a great software name if there ever was one), and the Python utility pynliner to convert the HTML generated by the Jupyter nbconvert utility to a WordPress.com oriented form.

nb2wp HTML can be pasted, (read Benny’s instructions), into the WordPress.com block editor. My post Using jodliterate was composed in this way.

nb2wp notebook HTML is treated as a single WordPress.com block editor block. This makes it hard to use the block editor which brings me to the next hack.

Hack #2: nb2subnb

Notebooks are stored as simple JSON files. It’s easy to split notebooks into n smaller notebooks. The following Python program, (available here), cuts notebook files into smaller sub-notebooks.

In [1]:
def nb2subnb(filename, *, cell_type='markdown', 
             single_nb=False, keep_cells=[], keep_texts=[]):
    (nb2subnb) splits out typed cells of jupyter 
    notebooks into n sub-notebooks.


       # split into n markdown cell notebooks

       # split into n code cell notebooks

       # all markdown cells in single notebook

       # code cells with numbers in range as single notebook
           cell_type='code', single_nb='True', 

       # markdown cells with strings 'Bhagavad' or 'github' 

       # all code cells in range with string 'pacman' 
           keep_texts=['pacman'], keep_cells=list(range(30)))

    with open(filename) as in_file:
        nb_data = json.load(in_file)

    # notebook file name without extension/path
    nbname = os.path.basename(os.path.splitext(filename)[0])

    nb_cells, one_cell, nb_files = dict(), list(), list()

    for cnt, cell in enumerate(nb_data['cells']):
        if nb_data['cells'][cnt]['cell_type'] == cell_type:

            if not single_nb:
                # single cell notebooks
                nb_cells, one_cell = dict(), list()
                if 0 == len(keep_cells) or cnt in keep_cells:
                    if text_in_source(cell, keep_texts):
                        nb_cells["cells"] = one_cell
                        nb_cells = insert_nb_metadata(
                            nb_data, nb_cells)
                        nb_out_file = NB_DIRECTORY + \
                            nbname + '-' + cell_type + \
                            '-' + str(cnt) + '.ipynb'
                        with open(nb_out_file, 'w') as out_file:
                            json.dump(nb_cells, out_file,
            elif single_nb:
                # single notebook with only (cell_type) cells
                if 0 == len(keep_cells) or cnt in keep_cells:
                    if text_in_source(cell, keep_texts):
                        nb_cells["cells"] = one_cell

    if single_nb:
        nb_out_file = NB_DIRECTORY + \
            nbname + '-' + cell_type + '-only.ipynb'
        nb_cells = insert_nb_metadata(nb_data, nb_cells)
        with open(nb_out_file, 'w') as out_file:
            json.dump(nb_cells, out_file, 

    # list of generated sub-notebooks
    return nb_files

nb2wp can be applied to the sub-notebooks to produce smaller, more block editor friendly, HTML files. Blog posts can be put together by picking and pasting the smaller blocks.

Combining nb2wp and nb2subnb

nb2wpblk combines the actions of nb2wp and nb2subnb to generate n HTML files.

In [2]:
# append nb2* script directory to system path
import sys
In [3]:
# notebook file
nb_file = r'C:\temp\nb2wp\UsingJodliterate.ipynb'
In [4]:
nb2subnb_opts = {
    'single_nb': False,
    'cell_type': 'code',
    'keep_cells': [2, 8, 21],
    'keep_texts': []
In [5]:
import nb2wput as nbu

# split notebook into selected parts and convert to HTML 
nbu.nb2wpblk(nb_file, nb2subnb_parms=nb2subnb_opts)
Using template: full
Using CSS files ['C:\\temp\\nb2wp\\style.css']
Saving CSS to C:\temp\nb2wp\tmp\style.css
C:\temp\nb2wp\tmp\UsingJodliterate-code-2.html: 7054 bytes written in 4.488s
Using template: full
Using CSS files ['C:\\temp\\nb2wp\\style.css']
Saving CSS to C:\temp\nb2wp\tmp\style.css
C:\temp\nb2wp\tmp\UsingJodliterate-code-8.html: 4715 bytes written in 4.177s
Using template: full
Using CSS files ['C:\\temp\\nb2wp\\style.css']
Saving CSS to C:\temp\nb2wp\tmp\style.css
C:\temp\nb2wp\tmp\UsingJodliterate-code-21.html: 8683 bytes written in 5.437s

The utilities referenced in this post are available on Github here. Help yourself and blog better!

Blogging Bad 2013

Another year of blogging bad. My mother’s death and work were major distractions this year; I fell way short of my post goals but still managed to exceed the previous year’s hit count and set a new high.  To show their appreciation the good algorithms at WordPress.com sent us an annual report. Mine follows:

The WordPress.com stats helper monkeys prepared a 2013 annual report for this blog.

Here’s an excerpt:

The concert hall at the Sydney Opera House holds 2,700 people. This blog was viewed about 11,000 times in 2013. If it were a concert at Sydney Opera House, it would take about 4 sold-out performances for that many people to see it.

Click here to see the complete report.

Too Busy to Blog

Blogging is like going to the gym. You tell yourself you’re going to do it everyday and then you don’t.  The last two months have been all about my mother’s death and work.  Any remaining hours  were siphoned off by my other hobbies: photography and reading. Yeah I count reading as a hobby.

If we’re going to have the long happy writer-reader relationship that we’re all looking for you are going to have to put up with my ticks. I will enumerate them for you:

  1. I blow hot and cold on things. I am either all in or all out. If I am blogging that’s pretty much all I am doing. If I am taking pictures or programming that’s pretty much it. Balance is for rocks on pinnacles not me.
  2. I always return to my passions. I never give up on things I just put them aside. My affection for amateur astronomy has not gone away it’s just difficult to indulge it in the wretched quasi-opaque low altitude skies of St. Louis.  This city has many charms but clear skies is not one of them.
  3. I don’t give a crap about what people think. This is a problem for anyone that pretends to write. Authors, even lowly bloggers, cannot ignore their audience or they won’t have one. My manly impulse is to ignore you, but  I will, on occasion, profusely apologize and beg you to keep reading. It’s all crocodile tears. My apologies are as insincere as Obama’s: another guy that doesn’t give a crap about what you think.
  4. I will never change: at least while alive. Guys get this instantly.  A few women have vainly tried to correct my bad habits; they didn’t succeed.

To end June on a happy note and, more importantly, to test a nifty WordPress layout feature here’s a collection of recent images.  Click on any one to enlarge. All these images, and thousands more, are always on view on SmugMug. Next month I will be a better boy and write the epoch defaming rubbish you all love and crave.

Playing the Blog hit game

On June 5th 2012 my little blog set an all time hit record: 198 robots, spammers and readers incremented my counters. 198 hits would be embarrassing for a major blog like Instapundit but for Analyze the Data not the Drivel it was a “hitnotic” day. I always attribute my triumphs to my utter manly awesomeness but I had to ask; was anything else going on June 5th, 2012?  Nothing much except the last transit of Venus in this century! The masses were searching for “transit” and hundreds landed on this little entry I wrote a few months ago.

It takes time for a blog post to burrow into cyberspace. Google and Bing are always prowling blog sites and will pick up new posts within minutes but it takes about two weeks before worldwide indexes are updated.  Once a post is on search engines readers will find it and when they do it will meet one of these three fates.

  1. Nobody ever reads it again. This is the fate of most of my posts. I have posts that my dog, if I had a dog, wouldn’t read. It’s too bad because some of my finest lyrical unhinged rants are my least read posts.
  2. It gets lots of hits followed by a quick return to few or none. My popular posts follow this pattern. Now that the 2012 transit of Venus is history people will stop searching for it. Popular posts fade faster than old Botox saturated actresses so enjoy your hits while they last!
  3. It gets legs and keeps sucking in hits for weeks, months and years. My normal traffic comes from half a dozen leggy postings. My leggy-est posting is an Inception movie review that I wrote almost two years ago; it’s still generating ten to twenty hits per week. Its ok people nobody really got that movie.

Finally, the blog hit game is a long game; you have to keep playing. The best sports analogy is golf. Golf is the world’s hardest game. The gap between a perfect round of eighteen and what the best players are capable of is insurmountable. Nobody will ever shoot an honest eighteen. A best ball foursome of Buddha, Christ, Mohammad and the archangel Gabriel couldn’t shoot an honest eighteen. The Sun exploding tomorrow is more likely than on honest eighteen. Golf sets a bar so high it will never be breached. Artists have similar bars. The perfect novel is impossible. The perfect song is impossible. The perfect sculpture is impossible and I dare say the perfect blog post is impossible but then it’s the impossibility of perfection that keeps things interesting. Keep at it and the hits will come.