How to use a python virtualenv with sudo?

68,134

Solution 1

The issue is almost certainly that when you run sudo, the virtualenv environment variables, aliases, functions, etc aren't being carried over.

The solution would be to explicitly run the virtual environment's Python executable with sudo. For example if your virtualenv is ./AwesomeProject, then you could run sudo ./AwesomeProject/bin/python <script> to use the script with the virtualenv with root privileges.

Solution 2

Depending on your particular use-case this may or may not solve your problem, but this wasn't yet mentioned here. Say, you want to run a Python script that was installed in your virtual environment, and you need to setuid(0) it, i.e. you want to run it as superuser. Say, your script is called myscript.py, then, you can do it like this:

(.venv) $ sudo -E env PATH=$PATH ./myscript.py

Explanation

(.venv) $ is the shell's prompt, you don't need to type it, it just shows that you are currently using some virtual environment, and you are not a privileged user.

sudo -E will tell sudo that when starting a process, it needs to copy the environment variables from your current shell environment. So, if you have any extra variables defined in .venv/bin/activate script, they should stick around while you are root.

env PATH=$PATH when using sudo -E not all environment variables are preserved, specifically, and most importantly, the PATH may be removed. The specifics of this behavior will depend on your sudoers file. This, however, will circumvent whatever's written in sudoers file, as it will copy the PATH explicitly into environment sudo creates for the new process. This is important because when your system resolves shebang comment in your myscript.py, it will look in the PATH variable, and the first directory to match the requirement for interpreter will be used. venv on the other hand, sets up the shell environment in such a way that the directory containing the symlink to the chosen Python interpreter appears first, thus causing system to locate the desired Python before any other Pythons on system path.

Solution 3

Just stumbled across this and for others who may find the same issue, Ken is correct that the env variables are not being carried over. The solution I used was to add the following lines to my script. This has the added benefit of always loading the virtual environment directly from the script. (Meaning you can use the script with crontab or launchd without any other workarounds.)

base_dir = os.path.dirname(os.path.abspath(__file__))
activate_this = os.path.join(base_dir, 'venv/bin/activate_this.py')
execfile(activate_this, dict(__file__=activate_this))

More background here: https://virtualenv.pypa.io/en/latest/userguide.html#using-virtualenv-without-bin-python

Solution 4

Sometimes you need the $PATH updated because the script runs other programs. For example pypi-install needs py2dsc-deb in the PATH. This command works: sudo sh -c ". venv/bin/activate ; pypi-install $PACKAGE"

Share:
68,134

Related videos on Youtube

Marco P.
Author by

Marco P.

Updated on September 18, 2022

Comments

  • Marco P.
    Marco P. almost 2 years

    I am trying to make a python environment separate from the system one (using virtualenv) in a directory which is not under /home, because I need to use it to build other software that has to be accessible to multiple users. I can create and activate the virtualenv all right, but when I sudo some command (for example to make or compile other software), it is the system python that is used (I can tell because of the available modules).

    Since on Ubuntu it is not a good thing to use the root user, is there a way to tell sudo to use a virtualenv? Or maybe this is not the correct approach, and I should make a completely new python installation?

    I am using the 64bit version of Ubuntu 12.04 (and python 2.7).

    • John Drinane
      John Drinane about 7 years
      Does the following work? sudo $(which python) <script>
  • OrangeTux
    OrangeTux almost 11 years
    You could also let the first line of your script point to the Python binary in your virtualenv. #!<virtualenv_dir>/bin/python.
  • google cloud sucks
    google cloud sucks almost 5 years
    Ugh, annoying that this is only solution so far. On Mac, sudo python uses python from the virtual env.
  • belvederef
    belvederef over 4 years
    @OrangeTux I tried what you suggested and it does not work for me when running the script with sudo python3 my_script.py
  • Pe Dro
    Pe Dro about 4 years
    @kenkinder @gaefan In my case, I get Command not found when using sudo ./home/pradan/.virtualenvs/sk/bin/python3 main.py where main.py is my script and sk is name of my virtual env.