Luis Masuelli
Luis Masuelli

Reputation: 12343

Is there a way to deactivate a virtualenv inside python interpreter? i.e. analogous of deactivate_this

I have this script (this is the beginning of a wsgi script for openshift applications). This script activates a virtualenv using the in-python system environment.

#!/usr/bin/python
import os

virtenv = os.environ['OPENSHIFT_PYTHON_DIR'] + '/virtenv/'
virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
try:
    execfile(virtualenv, dict(__file__=virtualenv))
except IOError:
    pass

What's the opposite? i.e.: is there an analogous way to do a "deactivate_this"? (a file like that does not seem to exist in any of my created virtualenvs)

This means: I don't want to reinvent the wheel. I'm asking if there's a prepared command line for that.

Upvotes: 4

Views: 1373

Answers (2)

Luis Masuelli
Luis Masuelli

Reputation: 12343

This is a complement to the answer @TomDalton gave. Althought there's no an automatically provided way to do this, there are means provided by the activate_this script.

First, it is important to remember that this line:

execfile(virtualenv, dict(__file__=virtualenv))

is calling the function without passing a dictionary for globals nor a dictionary for locals. This will imply that the execution context will be the current globals (i.e. the one from the calling line) and locals objects. such line will alter the variables we currently have -- will override the calling environment See here for docs about.

In that way, since variables are overriden, activate_this gives us some variables like:

old_os_path = os.environ['PATH']
#the previous PATH

prev_sys_path = list(sys.path)
#the old Python Path

if sys.platform == 'win32':
    site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
    site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
#site_packages is the extended venv's packages dir.
#sys.path is affected here

sys.real_prefix = sys.prefix
#the old system prefix

So we can restore such variables if we want a manual deactivation:

import sys, os, site
sys.path[:0] = prev_sys_path #will also revert the added site-packages
sys.prefix = sys.real_prefix
os.setenv('PATH', old_os_path)

Upvotes: 2

Tom Dalton
Tom Dalton

Reputation: 6190

I believe the short answer is No.

The medium answer is "Not unless you have saved the state of the environment before executing activate_this.py".

Perhaps a way to achieve what you want is to separate the parts of your app that need to run in the venv from those that don't. Then use a subprocess to activate the venv and run whatever you want, when the subprocess terminates, your original process (in the original environment) can resume.

NB This post (How to leave/exit/deactivate a python virtualenv?) suggests the activation may provide a shell function to put-everything-back. You'd need to check if your activate_this.py script provides anything similar, though it sounds like you have already checked this.

Upvotes: 3

Related Questions