0

I've installed IPython globally with the distro's package manager. When I launch it from a virtual environment I get the message UserWarning: Attempting to work in a virtualenv. …. I've tried to use the methods described by florisla on Determine if Python is running inside virtualenv to figure out whether it's working properly. The piece of code I'm actually running is slightly modified to print out all the booleans when run:

# 1) VIRTUAL_ENV environment variable
# Both 'virtualenv' and 'venv' set the environment variable '$VIRTUAL_ENV' when activating an environment. See PEP 405.
# You can read out this variable in shell scripts, or use this Python code to determine if it's set.
import os
running_in_virtualenv = "VIRTUAL_ENV" in os.environ
# alternative ways to write this, also supporting the case where
# the variable is set but contains an empty string to indicate
# 'not in a virtual environment':
running_in_virtualenv1a = bool(os.environ.get("VIRTUAL_ENV"))
running_in_virtualenv1b = bool(os.getenv("VIRTUAL_ENV"))
# The problem is, this only works when the environment is activated by the 'activate' shell script.
# You can start the environment's scripts without activating the environment, so if that is a concern, you have to use a different method.
print("1a:", running_in_virtualenv1a)
print("1b:", running_in_virtualenv1b)

# 2) sys.real_prefix and sys.base_prefix
# Virtualenv points 'sys.prefix' to the Python installed inside of the virtualenv as you would expect.
# At the same time, the original value of 'sys.prefix' is also made available as a new attribute of 'sys': 'sys.real_prefix'. This is what we're using to detect if we're in a virtualenv.
import sys
running_in_virtualenv = hasattr(sys, "real_prefix")
# There's a problem though: 'venv' and 'pyvenv' do this differently from 'virtualenv' -- they don't set 'real_prefix'. Instead, they set 'base_prefix' to a different value from 'sys.prefix'.
# So to be safe, check both as suggested in hroncok's answer:
import sys
virtualenv_prefix = getattr(sys, "real_prefix", None)
venv_prefix = getattr(sys, "base_prefix", sys.prefix)
running_in_virtualenv2 = virtualenv_prefix or venv_prefix != sys.prefix
print("2:", running_in_virtualenv2)

Now, if I run this code from outside of a virtual environment I get three False both with the python3 shell and ipython3, but if I'm in a virtual environment, IPython returns False for the last boolean (running_in_virtualenv2), while python3 returns True for all of them.

Can I still tinker within my virtual enviroment, using IPython, without risk of messing up the system installation?

Arch Stanton
  • 287
  • 5
  • 10

1 Answers1

1

Mostly the virtual environment is about modifying your import search path.

import pprint
import sys

pprint.pprint(sys.path)

Inspect the path in different environments, and choose a directory element that corresponds to your venv, for example the directory that shows up when you type $ which python. Have your code change its behavior based on the presence of that directory.

J_H
  • 9,521
  • 1
  • 16
  • 31
  • `pprint.pprint(sys.path)` has `/home/arch/src/python/scratch/.scrvenv/lib/python3.7/site-packages` at the top of the list, if run from `ipython3`, or at the bottom if run from `python3`. Does that mean that I'm safe? (I'm trying to keep things simple as I'm just beginning to learn Python. I'd like to know if I'm safe tinkering with packages. It doesn't matter if I break a script but I'd rather not break the whole system.) – Arch Stanton Oct 26 '19 at 17:13