Skip to content

Instantly share code, notes, and snippets.

@datavudeja
Forked from bassio/virtualenvcontext.py
Created February 9, 2025 21:59
Show Gist options
  • Save datavudeja/c1bf67423a9dbf82d442bfecaef0939e to your computer and use it in GitHub Desktop.
Save datavudeja/c1bf67423a9dbf82d442bfecaef0939e to your computer and use it in GitHub Desktop.
import os
import shlex
import subprocess
from subprocess import Popen
from pathlib import Path
class VirtualEnv(object):
"""
Create a VirtualEnv context manager.
It changes the environment variables to that of the virtualenv through bin/activate on __enter__
and returns it back to the previous state on __exit__.
Example use:
my_virtual_env = VirtualEnv("/path/to/my/virtualenv")
with VirtualEnv(my_virtual_env) as env:
cmd = ['script_or_executable_in_venv', '--arg1', '--arg2']
p = subprocess.call(cmd) #this calls the subprocess as if running in the virtualenv
"""
def __init__(self, path_to_virtualenv):
path_to_virtualenv = Path(path_to_virtualenv).absolute()
if not path_to_virtualenv.exists():
raise NotADirectoryError(path_to_virtualenv)
self.path_to_virtualenv = path_to_virtualenv
self.venv_bin_activate = self.path_to_virtualenv / 'bin' / 'activate'
self.python = self.path_to_virtualenv / 'bin' / 'python'
if not self.venv_bin_activate.exists():
raise FileNotFoundError(self.venv_bin_activate)
if not self.python.exists():
raise FileNotFoundError(self.python)
cmd = '/bin/bash -c "source {} && python -c \'import os; print(dict(os.environ))\'"'
self.cmd = cmd.format(str(self.venv_bin_activate))
p = Popen(shlex.split(self.cmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)
self.p = p
self.env = eval(str(p.stdout.read(), 'utf-8'))
self.current_env = os.environ.copy()
self.p.terminate()
def __getitem__(self, item):
return self.env[item]
def __enter__(self):
os.environ.clear()
os.environ.update(self.env)
return self.env
def __exit__(self ,type, value, traceback):
os.environ.clear()
os.environ.update(self.current_env)
return self.current_env
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment