Xiaohong Deng

五 14 十二月 2018


Pelican: Python 3 or Upgrading to Python 3

Making a Static Blog with Pelican is a great tutorial for beginners to start with Pelican. It was in Python 2 because back then fabric is incompatible with Python 3. Now Pelican has moved to invoke by default which is very similar to fabric which supports Python 3 now. Both invoke and fabric are authored by the same person. It's time to use Pelican with Python 3 and enjoy the automation from invoke.

Getting Started

You can either install all the dependencies in a virtual environment or not. For me, I chose to install Pelican in a conda env.

conda create -n pelican python=3.6
source activate pelican


After installing Pelican, you should run pelican-quickstart to get a updated Makefile and tasks.py. The latter should be used to replace fabfile.py if you have a Pelican working directory created with Python 2.

fabric API was reorganized since v2.0. invoke is more like Fabric2. So command line automation works differently now. To call functions defined in tasks.py you have to prepend @task to each function meant to be called in command line and add a parameter which will be set to a Context by the decorator. Check out the following code snippet to get a hang of it.

Note: When calling a function in command line you must replace underscores with hyphens.

# in command line use `invoke make-entry -p port_string` or
# `invoke make-entry` to go with default value
def livebuild(c, port=8080):
    run('make clean')  # 1
    run('make html')  # 2
    os.chdir('output')  # 3
    server = livereload.Server()  # 4
    server.watch('../content/articles/*.md',  # 5
        livereload.shell('pelican -s ../pelicanconf.py -o ../output'))  # 6
        livereload.shell('pelican -s ../pelicanconf.py -o ../output'))
    server.watch('../pure/',  # 7
        livereload.shell('pelican -s ../pelicanconf.py -o ../output'))  # 8
        livereload.shell('pelican -s ../pelicanconf.py -o ../output'))
    server.watch('*.html')  # 9
    server.watch('*.css')  # 10
    server.serve(liveport=35729, port=port)  # 11

def enter_dns_file(c):  # 1
    with open('output/CNAME', 'w') as f:

# in command line use `invoke make-entry -p` to go with True or
# `invoke make-entry` to go with default value False
def github(c, publish_drafts=False):  # 2
    try:  # 3
        if os.path.exists('output/drafts'):
            if not publish_drafts:
                run('rm -rf output/drafts')
    except Exception:

    run('ghp-import output')  # 4
    run('git push'
          ' your_github_personal_project_domain'
          ' gh-pages:master')  # 5
    run('rm -rf output')  # 6

def one_click(c):

If you want to call any function in command line as tasks, you must set the first parameter, this will be initialized to a Context by task()

For functions like github() which has a default boolean valued parameter, if you want to call it in command line you can explicitly specify a flag -p to set it to true, or omit it to set it to the default value which is false

if you don't need any parameters you still must set a parameter which is set to a Context by task by default, then you can call them in command line. Otherwise you get an error As you can see if you want to call them in other functions you must explicitly pass a Context to them

If you remove c for github() it will still work but publish_drafts will be set to a Context, being called as a command line task or within another function

Context can serve as a connection such that you can call shell commands on it. Or directly call shell commands using invoke.run. Either way you must define a Context parameter for most functions, which is annoying.

Wrap Up

That's pretty much all you need to know about Pelican in Python 3. Enjoy the ride with Pelican.

Go Top
comments powered by Disqus