Pyenv choose virtualenv directory
Asked Answered
T

10

31

I just began to use pyenv to manage my python versions, and began to use the pyenv virtualenv plugin to manage my virtualenvs, and so far, I have loved it. One thing I miss however, is that with virtualenv, you could actually place virtual environments in repository directories so that your repository was a completely reproducible environment. Does anyone know of a way to choose the directory of your virtualenv in pyenv?

Tessellation answered 22/5, 2015 at 23:54 Comment(0)
A
22

Short answer: You can’t, as far as I know.

It wouldn’t really work either, right? If you use pyenv virtualenv to install a virtualenv into a repo, and you clone that repo to another machine… how would pyenv on the new machine know to take control of the virtualenv in the repository?

Also, “you probably shouldn’t do that”. Virtualenvs are not 100% decoupled from the underlying Python installation, and aren’t really all that portable. And do you really want to litter your repositories with a bunch of easily replicated junk? The “right” way to go about things is probably to to maintain a requirements.txt for pip — that way you can easily reproduce your development environment wherever you clone your repo.

That all said, there’s nothing stopping you from using plain old virtualenv to create a virtualenv anywhere you like, even if you installed virtualenv into a Python interpreter under pyenv control. That virtualenv itself will of course not be administered by pyenv, but you can still use it as you always did…

Age answered 11/4, 2016 at 13:56 Comment(2)
As someone looking at this question, I have a requirements.txt and a script that generates a virtualenv. I want a command that looks in the current path for virtualenvs, and don't want to manage "global" virtualenvs. I want my virtualenv to exist in a directory.Ellerd
you can and it is easy and not bothersome at all - I have added my usual workflow below.Tarsuss
B
9

I use the following commands:

pyenv local 3.9.16

And then

python -m venv virtualenv

It works

Bagpipes answered 10/3, 2023 at 11:34 Comment(0)
C
6

Here is a GitHub issue on the project tracker asking about this: https://github.com/pyenv/pyenv/issues/802

The reply by a project collaborator was:

You can just create virtualenv in any location. To use it from pyenv, create symlink to the environment in ~/.pyenv/versions

although I must say I'm not very satisfied with this solution.

Carbon answered 10/12, 2019 at 13:8 Comment(0)
P
3

There's a workaround

In your project directory, create a .python-version file. Assuming you already installed some virtual environment using pyenv-virtualenv, then append this line to it(you may want to change the version number):

3.7.1/envs/[email protected]

Whenever you enter into the directory, the correct python version will be used, and it works pretty well.

Providence answered 27/10, 2018 at 18:11 Comment(2)
Alternatively pyenv will create this file for you in your current path with the command pyenv local <name_of_virtualenv>.Spall
Could there be a global location of this fileNorway
B
2

How about:

pyenv install -s 3.8.3 # install preferred version if needed
PYENV_VERSION=3.8.3 python -m venv /tmp/your/prefered/dir ; source /tmp/your/prefered/dir/activate

Note that this method uses venv, not virtualenv, which is slightly different, but a part of a standard library.

Bewail answered 4/10, 2021 at 19:25 Comment(0)
T
2

I use the simple recipe of

  1. python -m venv virt to create the local venv
  2. Link the venv to pyenv with ln -s <local virt> ~/.pyenv/versions/<venv name>
  3. Now you can do pyenv local <venv name> and all other normal operations from pyenv with this venv.

For the interested I have made two CLIs

  • pyenv-here to create a new venv and set local dir in one go
  • pyenv-link to link a local virt to pyenv
Tarsuss answered 10/10, 2022 at 18:17 Comment(1)
This should be the acccepted answerBrindled
E
0

Slightly left-field answer, but I ended up writing a hacky equivalent of pyenv that looks for a virtualenv in a directory and its parents because pyenv doesn't really seem to support this as layed out in the answer about.

I called this script enpy, put it on my path and then called e.g. enpy -c import sys; print(sys.executable)

#!/usr/bin/python3

import os
import sys

from pathlib import Path


NAMES = ("venv", "env", ".env", ".venv")


def find_python():
    cwd = Path(os.getcwd())
    for direc in [cwd] + list(cwd.parents):
        for p in NAMES:
            venv = direc / p
            if venv.exists():
                return venv / "bin" / "python"
    else:
        raise Exception("Could not find python")


python = find_python()
os.execvp(str(python), [str(python)] + sys.argv[1:])

Ellerd answered 14/9, 2022 at 11:7 Comment(0)
A
0

The top comment is wrong; you certainly can.

Once you create your virtual environment with pyenv virtualenv 3.9.15 your-environment-name, you can specify the directories in which this environment will be used automatically with the following command. In your desired directory, run:

pyenv local your-environment-name

The command will create the necessary .python-version file that includes the name of your environment. From now on, every time you enter the folder, the specified environment will be used.

Avalanche answered 13/11, 2022 at 2:43 Comment(1)
The question refers to where the venvdir is gonna be located, not what's gonna activate when you enter,Brindled
L
0

If you want to just use pyenv specific python version and create virtual env from it in wanted directory, you can for example do this:

~/.pyenv/versions/3.10.8/bin/python -m venv my/path/to/venv

Larimor answered 16/11, 2022 at 17:54 Comment(0)
M
-1

To build on-top of a previous comment, you can add this to your .zshrc:

pyC () {
    location="requirements.txt"
    venvName=".venv"
    
    # Parse flags
    while getopts "r:e:" opt; do
        case $opt in
            e) venvName=$OPTARG ;;
            r) location=$OPTARG ;;
            \?) echo "Invalid option: -$OPTARG" ;;
            :) echo "Option -$OPTARG requires an argument.";;
        esac
    done

    # Remove existing virtual environment if it exists
    [ -d $venvName ] && rm -rf $venvName
    
    # Determine Python version (global or local)
    pyVersion=$( [ -f .python-version ] && echo "local" || echo "global" )

    # Check pyVersion, create version file, virtual environment, activate it
    pyenv version-name $pyVersion | xargs -I {} pyenv local {} && python -m venv $venvName
    source $venvName/bin/activate && pip install --upgrade pip
    
    # Install requirements if file exists, otherwise print message
    [ -f $location ] && pip install -r $location || echo -e "\nFile $location not found"
}
Moneychanger answered 12/9, 2022 at 19:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.