Repository: pypa/pipenv

Issue:
How to set the full name of the virtualenv created
When using inside my project directory `PROJECTDIR`

    pipenv install

`pipenv` creates a virtualenv named `"PROJECTDIR-<someid>"`.  How can I specify this full name myself, say to call the virtualenv just `"PROJECTDIR"`?

And how can I tell `pipenv` to use an existing virtualenv for this directory and just add the new packages from the `requirements.txt`?


Discussion:
This has been discussed multiple times in the past. You can search the issue tracker for similar entries. To sum things, it is not possible (at this time; can’t say for the future) to specify the name of the virtualenv, since Pipenv relies on this information to associate it to your project. The alternative is to set environment variable `PIPENV_VENV_IN_PROJECT` to tell Pipenv to look for the a directory named `.venv` inside your project (the same level as `Pipfile`).

To import dependencies from `requirements.txt`, use `pipenv install -r`. This converts the requirements file to a Pipfile, and use it to create the environment. There is not way to specify an existing virtualenv (unless you name it exactly the same as Pipenv would).

Most of the above is mentioned in detail in the documentation. Please check out relevant sections for more information.

https://docs.pipenv.org
I know that I can set `PIPENV_VENV_IN_PROJECT` environment variable, but I would like to set it in a project specific way and store that information into my git repository to share it. Would it be possible to add a section, let's say, to `setup.cfg` to store that information?

@kmpf I believe the goal of the project is really to remain as simple and straightforward as possible and to avoid introducing additional setup complexity or configuration overhead.  By sticking firmly to deterministic hashing of project paths _and providing the alternative of .venv directories_, there is never any ambiguity about where pipenv-managed environments will be stored.

I understand what you want and I get why you want it, I'll go even further and say that I don't even think it's unreasonable. However I do think it is out of scope -- it is something that has been requested a few times though, and this is an open source project.  I would strongly encourage anyone who needs additional layers of functionality to feel free to build and publish tools that provide that

Thanks for the report, and thanks for using our tools :) 
My workaround:

Current versions of pipenv respect an existing virtualenv, so if you want to control the name you could (with virtualenvwrapper)
```
mkvirtualenv [-a ~/projects/my-project-dir ] [-p $my_python_executable] my-project
pipenv install --dev
```

pipenv install will notify that it will use the existing virtualenv. In order to keep using it, you'll have to remember to `workon my-project` before using pipenv.
My use-case: As a **spaceship-prompt** user I was annoyed that `PROJECTDIR-<someid>` atrocity was displayed at the end of my prompt:
![image](https://user-images.githubusercontent.com/20413685/55796758-04637a80-5acb-11e9-8c7e-61dd27873108.png)
My workaround: modify the way spaceship-prompt displays virtualenv name.   

Either  
add `venv=${venv%-*}` before `spaceship::section` in `$SPACESHIP_ROOT/sections/venv.zsh`  
or  
run `sed -i '39i\  venv=${venv%-*}' $SPACESHIP_ROOT/sections/venv.zsh`.  

Works with `spaceship-prompt 3.11`. Replace `sed` to `gsed` (after `brew install`ing it) if MacOS user.  
Result:  
![image](https://user-images.githubusercontent.com/20413685/55799186-07fa0000-5ad1-11e9-818a-5d242e111eba.png)

Is there a way to retrieve the name of the venv associated with a project? I mean, when I am not directly in the project path, can I figure out the name of the venv associated with it?
> Is there a way to retrieve the name of the venv associated with a project? I mean, when I am not directly in the project path, can I figure out the name of the venv associated with it?

The venv name is deterministic and based on the path to the Pipfile. It is just `project-xxxxxxxx`, unless your project name needs to be sanitized of dangerous symbols and/or truncated to 42 characters. The code for generating the name is in `pipenv.project.Project._get_virtualenv_hash()`.

This one-liner will get you the hash:
```
python -c 'import sys; import base64; import hashlib; print(base64.urlsafe_b64encode(hashlib.sha256(sys.argv[-1].encode()).digest()[:6]).decode()[:8])' /path/to/project/Pipfile
```
One of my main issues with not being able to choose a name for the virtual environment is that it doesn't take into account varying folder structures. I usually follow a common convention and like to nest my source code inside a `/src` directory of my main project folder. In the `/Users/NAME/.local/share/virtualenvs` directory every virtual env looks like:

```
src-Q4dXJo6L
src-ha_K95Ys
...
```
This makes it a little harder to distinguish between them.

This is also problematic when you have a `frontend` and `backend` in your repo, each with separate Pipenv files for separate dependencies. Again, I'd ideally like to name the project `PROJECT-frontend` and `PROJECT-backend`. With the hash suffix on both of those.

It would be nice to have a little control on the virtual environment naming.
>In the `/Users/NAME/.local/share/virtualenvs` directory every virtual env looks like

So you bought 10 red Ferrari's and now, looking at your garage, you don't know any more which one you used yesterday. There are a few cases where this is inconvenient (like, which one did I put the dead guy in), but most of the time, you just want to get from A to B in style.

Given your approach of looking at the virtualenv home, a quick look in `src-*/lib/*/site-packages/` will reveal which is which, but the easiest approach is simply to go your project directory and use `pipenv --venv`, so you know the one used by that project. Heck, if you don't like the double shell spawning of pipenv shell, you can even do `source $(pipenv --venv)/bin/activate`.

All I see here, is cosmetics and minor inconvenience for things not done often. Can we move on?
This is what I use.  I just fork pipenv, add 3 lines, install it local. ( `pip install --user .` )

https://github.com/pypa/pipenv/compare/main...darelf:main

```
export PIPENV_CUSTOM_VENV_NAME=mycustomname
pipenv install
pipenv shell
etc. etc.
```

Thanks @darelf! Good idea.
@darelf Care to open a PR patch against the main library since it seems that more than a couple users would like this feature?

With all due respect to @techalchemy 's 2017 comment about it that closed the issue, I think it could be supported and may even reduce the number of support tickets if people can have predictable .virtualenv names configured as needed, non-default.

Resolving patch:
diff --git a/pipenv/environments.py b/pipenv/environments.py
--- a/pipenv/environments.py
+++ b/pipenv/environments.py
@@ -335,6 +335,9 @@ def initialize(self):
         approach, you may set this to '0', 'off', or 'false'.
         """
 
+        self.PIPENV_CUSTOM_VENV_NAME = os.getenv("PIPENV_CUSTOM_VENV_NAME", None)
+        """Tells Pipenv whether to name the venv something other than the default dir name."""
+
         self.PIPENV_PYUP_API_KEY = os.environ.get("PIPENV_PYUP_API_KEY", None)
 
         # Internal, support running in a different Python from sys.executable.
diff --git a/pipenv/project.py b/pipenv/project.py
--- a/pipenv/project.py
+++ b/pipenv/project.py
@@ -365,6 +365,9 @@ def get_name(name, location):
 
     @property
     def virtualenv_name(self) -> str:
+        custom_name = self.s.PIPENV_CUSTOM_VENV_NAME
+        if custom_name:
+            return custom_name
         sanitized, encoded_hash = self._get_virtualenv_hash(self.name)
         suffix = ""
         if self.s.PIPENV_PYTHON:


Test patch:
diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py
--- a/tests/integration/test_dot_venv.py
+++ b/tests/integration/test_dot_venv.py
@@ -161,3 +161,19 @@ def test_venv_in_project_default_when_venv_exists(PipenvInstance):
 
             assert venv_loc.joinpath('.project').exists()
             assert venv_loc == Path(venv_path)
+
+
+@pytest.mark.dotenv
+def test_venv_name_accepts_custom_name_environment_variable(PipenvInstance):
+    """Tests that virtualenv reads PIPENV_CUSTOM_VENV_NAME and accepts it as a name
+    """
+    with PipenvInstance(chdir=True, venv_in_project=False) as p:
+        test_name = "sensible_custom_venv_name"
+        with temp_environ():
+            os.environ['PIPENV_CUSTOM_VENV_NAME'] = test_name
+            c = p.pipenv('install')
+            assert c.returncode == 0
+            c = p.pipenv('--venv')
+            assert c.returncode == 0
+            venv_path = c.stdout.strip()
+            assert test_name == Path(venv_path).parts[-1]