9

I'm quite fond of Python's virtualenv, which facilitates maintenance of separate Python configurations. I'm considering embedding Python into a C++ application and was wondering how the embedded Python would behave with respect to virtual environments.

In particular, I'm intersted in knowing if it's possible to "select" a virtual environment based on some user-defined setting (e.g. by naming the virtual environment of interest in a configuration file).

2 Answers 2

5

The virtualenv documentation includes a Using virtualenv without bin/python section that hints at how to configure a virtual environment once the interpreter is already running.

To avoid hardcoding the path to the activate_this.py script, I use the following snippet:

def resolve_virtual_environment(override=None):
    """Fetch the virtual environment path in the
       process' environment or use an override."""
    path = os.getenv('VIRTUAL_ENV')
    if override:
        path = os.path.join(os.getcwd(), override)
    return path

def activate_virtual_environment(environment_root):
    """Configures the virtual environment starting at ``environment_root``."""
    activate_script = os.path.join(
        environment_root, 'Scripts', 'activate_this.py')
    execfile(activate_script, {'__file__': activate_script})

And you can use it like so:

if __name__ == '__main__':
    # use first argument is provided.
    override = None
    if len(sys.argv) > 1:
        override = sys.argv[1]
    environment_root = resolve_virtual_environment(override)

You can fetch the override value from a configuration file or something instead of from the command-line argument.

Note that you can only still use a single virtual environment pre-process.

Note: in contrast with using the interpreter bundled in the virtual environment, you have access to the packages installed for the interpreter you started. For example, when using a globally-installed Python, you will have access to the globally-installed packages.

Also make sure that you use a Python interpreter with a version that matches whatever version you used to create the virtual environment to make sure that the standard library (copied into the virtual environment) version matches the Python interpreter version.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this. I just needed to do that from the C++ side and mimicked your solution within Boost::Python. It works like a charm ! :)
This worked very well for me stackoverflow.com/questions/77881387/…
2

Yeah, definitely. It's just a matter of where you set the PYTHONPATH to (or what you compile in).

Make sure to check out pythonqt (not to be mistaken for PySide or PyQt .. it goes the other way, building a Python into a Qt C++ app.

5 Comments

Actually, I've been working on my own Python/C++ wrapper for writing a WSGI bridge in C++. This is all for educational purposes :-) I've got the WSGI stuff mostly figured out, and slowly integrating it with some FastCGI and SCGI handlers.
Is using virtualenv really just a "smart" way of modifying PYTHONPATH?
Looks like it to me. There's a bunch of window dressing around how it does things, figures paths out, 'partitions' itself and some configuration. I'm not trying to belittle virtualenv at all, but, it's not like it's a chrooted environment. It just sets things up with a notion of where 'home' is and is bundled with a set of tools for installing new modules that will also believe the same thing.
I know that, at least on Windows, It actually stores a copy of the interpreter inside the environment. Seems to me a like it's a little bit more elaborate than just messing with PYTHONPATH. Can you point me to any relevant (official) documentation?
Check out "compare & contrast with alternatives" in the virtualenv documentation. It seems workingenv just changed PYTHONPATH and ended up having some problems.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.