06 March 2009

Virtualenv Helper for Windows

If you're a fan of Ian Bicking's virtualenv library, and you should be, you've probably heard of Doug Hellmann's virtualenvwrapper bash script. Unfortunately for me I have to develop on Windows at work so this does me little good without a Bash shell (it may work under Cygwin, I haven't tried). Thankfully, Python runs everywhere and I was able to hack together a simple virtualenv management script for windows that handles most of my needs.

The script assumes you will store your virtual environments in the directory "C:\virtualenvs" (you can edit this in the script by changing DEFAULT_DIR_PATH), and supports listing, creating, removing and switching virtual environments from cmd.exe. To install, simply save the code below as env.py in your Python scripts folder, typically something like "C:\Python25\Scripts". You can then get a summary of the command line options by typeing "env.py -h" at a command prompt.

Here's the script:


import os
import shutil
from optparse import OptionParser

# default path to store virtualenv directories
# can be modified on a case by case basis with the -d option
DEFAULT_DIR_PATH = "C:\\virtualenvs\\"


def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-r", "--remove", action="store_true", dest="remove",
                      help="delete the virualenv")
    parser.add_option("-c", "--create", action="store_true", dest="create",
                      help="create the virtualenv if it does not already exist")
    parser.add_option("-l", "--list", action="store_true", dest="list",
                      help="list all current virtualenvs in directory")
    parser.add_option("-d", "--directory", dest="directory",
                      help="path to the directory containing the virtualenv")
                      
    (options, args) = parser.parse_args()
    
    dir_path = options.directory
    if dir_path is None:
        dir_path = DEFAULT_DIR_PATH
    
    # create the virtualenv directory if it does not exist
    if not os.path.isdir(dir_path):
        os.makedirs(dir_path)
        
    # list virtualenvs and exit
    if options.list:
        for item in os.listdir(dir_path):
            if os.path.isdir(os.path.join(dir_path, item)):
                print item
        return        

    # if we are not listing all envs we need a env name
    if len(args) != 1:
        parser.error("you must supply a virtualenv name")
    
    # store our paths
    env_name = args[0]
    env_path = os.path.join(dir_path, env_name)
    
    # does this env already exist?
    env_exists = os.path.isdir(env_path)
    
    # can't create and remove
    if options.create and options.remove:
        parser.error('iptions -c and -r are mutually exclusive')
    
    # prompt for confirmation and then delete the virtual env
    if options.remove and env_exists:
        resp = raw_input('remove directory "%s"? Y/n: ' % env_path)
        if resp == 'Y':
            print 'removing directory "%s"' % env_path
            shutil.rmtree(env_path)
        return
          
    # if the env does not exists we either create it (-c) or throw an error
    if not env_exists:
        if options.create:
            print os.system('virtualenv.exe %s' % env_path)
        else:
            parser.error('virtualenv does not exists. use the -c option to create it.')
            
    # activate the virtualenv
    script_path = os.path.join(env_path, 'scripts', 'activate.bat')
    os.system('cmd.exe /K "%s"' % script_path)
        

if __name__ == '__main__':
    main()

Here are some usage examples:


# List all environments
> env.py -l

# Switch to a new environment
> env.py myenviron

# Switch to a new environment and
# create it if it doesn't already exist
> env.py -c myenviron

# Remove an environment
> env.py -r myenviron

A couple notes:

  1. I've only tested this script on Windows XP with Python 2.5. It works for me. Use it at your own risk and all that.
  2. If you're developing with the Django development server DO NOT exit it using CTRL-BREAK as instructed. This will bork your command process and you'll have to close it out and open a new window. Use CTRL-C instead.

Update:

I've posted this script to Bitbucket where you can check out the latest changes and report any issues you find.

blog comments powered by Disqus