pyenv: Python Version Management

person using macbook pro

Photo by Christina Morillo on

pyenv does:

  1. Let you change the global Python version on a per-user basis.
  2. Provide support for per-project Python versions.
  3. Allow you to override the Python version with an environment variable.
  4. Search commands from multiple versions of Python at a time. This may be helpful to test across Python versions with tox.



For Mac OS, use homebrew.

$ brew update
$ brew install pyenv


Install virtualenv or virtualenvwrapper.

$ brew install pyenv-virtualenv
# or
$ brew install pyenv-virtualenvwrapper

Add the following configurations to the profile file.

# pyenv
# Load pyenv automatically by adding

# the following to ~/.bashrc: export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

# Add this if virtualenv is used
export PATH=$(pyenv root)/shims:$PATH
# For pyenv-virtualenvwrapper
# virtualenvwrapper
export WORKON_HOME=~/venv
export PROJECT_HOME=~/venv
pyenv virtualenvwrapper_lazy



$ pyenv versions
* 3.6.10 (set by /Users/dcho/.pyenv/version)

$ python --version
Python 3.6.10

$ pyenv global 3.7.6

$ python --version
Python 3.7.6

$ pyenv versions
* 3.7.6 (set by /Users/dcho/.pyenv/version)

virtualenvwrapper configuration

There are files for hooks and configuration is very straight forward.
I’d like to create a new folder named src for storing all the code base. Then, change directory to the new folder. Let’s see what I can do.

There is postrmvirtualenv file under $WORKON_HOME. In my case, it is ~/venv.
Let’s open up the file in vi editor and add some hooks.

$ vi ~/venv/postrmvirtualenv

# Add following to the file and save.
mkdir $path
cd $path

I’ve created a variable for the path of the source folder I mentioned. Then, create it and change directory to it.

Now, mkvirtualenv command lets you to create a new virtual env box and create a new folder called src under the project just created and change directory to the folder.

Let’s make some changes for workon command same as above.

I’d like to change directory to the src folder under the project once the project has been activated. Also, I’d like to change directory to the virtualenv root folder ~/venv once the project has been deactivated.

Open up postactivate and add below for activate behavior.


Open up postactivate and add below for activate behavior.


That’s it and enjoy.

Getting the last sub entries per entry

Now, I am trying to get the sizes of the last created versions of each contents.

Here’s the simple model diagram.


It looks just like a blog post and its comments. Here’s sample data.

Content model

id name
1 My Content 1
2 My Content 2

Version model

id parent_id size
1 1 100
2 1 200
3 1 300
4 2 400
5 2 500

The records with grayed background would be the result set as following table.

Expected result set (Versions only)

id parent_id size
3 1 300
5 2 500


My first thought was using group by with Max() function which requires a join or sub query. The 2nd thought was using distinct, but I wasn’t sure that grabbing the last ones only per parent. Anyway, here are the django orm and the sql queryset generated.
I tested with django-debug-toolbar’s debugsqlshell command which shows sql query strings per command with execution times. Below, I discard all execution times from the result because the result may vary based on the performance of the machine tested with.

$ ./ debugsqlshell

>>> Version.objects.distinct('parent').order_by('parent_id', '-created_at')
SELECT DISTINCT ON ("content_version"."parent_id") "content_version"."id",
FROM "content_version"
ORDER BY "content_version"."parent_id" ASC,
         "content_version"."created_at" DESC

Now I need to get size of each versions.

>>> Version.objects.filter(parent__owner=owner).distinct('parent').order_by('parent_id', '-created_at')
SELECT DISTINCT ON ("content_version"."parent_id") "content_version"."id",
FROM "content_version"
INNER JOIN "content_content" ON ("content_version"."parent_id" = "content_content"."id")
WHERE ("content_version"."is_archived" = false
       AND "content_content"."is_archived" = false
       AND "content_content"."owner_id" = '65ed9958-788e-11e6-9b70-a820663cfc41'::uuid)
ORDER BY "content_version"."parent_id" ASC,
         "content_version"."created_at" DESC

Now I need to add a filter to getting none-archived records and owned by a user.

>>> Version.objects.filter(parent__owner=owner).distinct('parent').order_by('parent_id', '-created_at').values_list("size", flat=True)
SELECT DISTINCT ON ("content_version"."parent_id") "content_version"."size"
FROM "content_version"
INNER JOIN "content_content" ON ("content_version"."parent_id" = "content_content"."id")
WHERE ("content_version"."is_archived" = false
       AND "content_content"."is_archived" = false
       AND "content_content"."owner_id" = '65ed9958-788e-11e6-9b70-a820663cfc41'::uuid)
ORDER BY "content_version"."parent_id" ASC,
         "content_version"."created_at" DESC

So far so good. 🙂
Oh, Now I want to get the total size of all the last versions.
I tried to add aggregation to get Sum() of size, and the django's orm results broken queries. If anyone knows how to get the result with django's orm, please let me know. I may buy you a cup of coffee or beer sometime.

Anyway, so I decided to use raw sql for the result and I didn't want to use python's sum() function because the number of records was arbitrary and may get lots of records that would make the application slow down.

Here's the last code snippet I used.

def get_storage_bytes_used(owner):
    Returns total bytes used for user.
    The calculation is Sum of latest versions of each `Content` records.

        owner (User): An owner of Content object.

        bytes_used (int): Total bytes used for a given user.
    query = '''SELECT sum(size) from (
        SELECT DISTINCT ON (v."parent_id") v."size"
        FROM "content_version" AS v
        INNER JOIN "content_content" AS c ON (v."parent_id" = c."id")
        WHERE (v."is_archived" = false
            AND c."is_archived" = false
            AND c."owner_id" = '%(owner_id)s'::uuid)
        ORDER BY v."parent_id" ASC, v."updated_at" DESC) as t'''
    context = {'owner_id':}

    with connection.cursor() as c:
        c.execute(query % context)
        bytes_used = c.fetchone()

    return bytes_used[0] or 0

Happy coding.

Inheritance Model, Polymorphism in Django

First of all, you need to install django-model-utils which allows you to create inheritance models.

ref. or

sudo pip install django-model-utils

Next, create your model.

from django.db import models
from model_utils.models import InheritanceCastModel

class Content(InheritanceCastModel):
    title = models.CharField(max_length=50)

class Video(Content):
    autoPlay = models.BooleanField(default=True)

class Audio(Content):
    Lyric = models.CharField(max_length=2000, null=True)


contents = Content.objects.all()
for content in contents:
    if hasattr(content, 'audio'):
        print 'This is audio'
        print 'This is video'

Also, you can add a filter as below.

list = Content.objects.filter(real_type__name = 'audio')

Django says “Unable to open” SQLite3

First of all, make sure the db path in your settings file.

import os
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': os.path.join(PROJECT_ROOT, 'talktrack.sqlite'), # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.

Then, check permissions below file and folders. (django needs full permissions)
1. db file.
i.e. yourapp.sqlite
2. /var/tmp
3. parent folder of db file
i.e. /var/www/yourapp
if the db file is in the folder. /var/www/yourapp/yourapp.sqlite

sudo chown -R user:group file-or-folder