Pipenv: Activate a pipenv environment without creating a new shell?

Created on 21 Oct 2017  路  14Comments  路  Source: pypa/pipenv

Is it possible to activate a pipenv environment without creating a new shell?

Example:

user@host:~/some_project$ pipenv activate
(some_project-OH5ik22OJ) user@host:~/some_project$

(Edit:) I should mention that this is possible by running

user@host:~/some_project$ . `pipenv --venv`/bin/activate

But I'm more interested in the "why spawn a new shell?"

Why am I asking?

I guess I don't really see the advantage of spawning a new shell. I do, however, see disadvantages:

  • When exiting the shell, your CWD changes to the path you were at when you spawned the shell, not the path you were in when exiting the shell
  • After exiting, you don't get your command history from when you were inside the shell

Examples of the disadvantages:

user@host:~/some_project$echo "outside of shell"
outside of shell
user@host:~/some_project$pipenv shell
<snip>
(some_project-AGMeXx6P) user@host:~/some_project$cd src
(some_project-AGMeXx6P) user@host:~/some_project/src$ echo "inside shell"
inside shell
(some_project-AGMeXx6P) user@host:~/some_project/src$ exit
user@host:~/some_project$ history | tail -n 10                # dir changed!
   1  echo "outside of shell"
   2  pipenv shell
   3  history | tail -n 10                                    # `echo "inside shell"` missing!

Describe you environment
  1. Windows, WSL, and Linux
  2. Python version: 3.5.2
  3. Pipenv version: 8.2.6

Most helpful comment

You can use pipenv 鈥攙env to get the location of the virtualenv and activate it like a normal virtualenv.

All 14 comments

@dougthor42, spawning a shell is the safe elegant solution to modify the environment without the need to maintain code for restoring it for every shell. When you exit from the shell, your previous env restored by the system.

Regarding the issues:

  • restoring the working directory - sounds like a feature
  • history not saved - this looks like a bug

When you exit from the shell, your previous env restored by the system.

So how is this different from simply running deactivate, like a standard venv?

restoring the working directory - sounds like a feature

For some, perhaps 馃槃

So how is this different from simply running deactivate, like a standard venv?

  • From the user point of view: "deactivate" is a non-standard venv command, and it works only if your shell is supported. "exit" is the standard way to exit a shell, and it works in any shell.
  • From the maintainer point of view: You don't need to maintain deactivate for all shells.

You can use pipenv 鈥攙env to get the location of the virtualenv and activate it like a normal virtualenv.

@techalchemy Yeah I realized that right after I posted, so it's part of the edit.

@nirs Ah, I didn't realized that deactivate had shell-specific code in it.

So I guess this issue devolves into a bug with the command history not being saved. Should I post that to the pew project or is it a bug with something else?

Activation and deactivation is shell and OS specific and requires extensive manipulation of paths which goes far beyond the scope of what pipenv is trying to do. pipenv shell is mainly a convenience operation, it is intended that you would primarily use pipenv run to do your heavy lifting.

As for command history, you can refer to the other issues on this topic: #876 #297

On windows, that is probably a pew bug. I think @techalchemy sums it up. Modifying the shell is beyond the scope of what pipenv in trying to accomplish! Thanks for using pipenv @dougthor42!

@erinxocon I understand why this issue has been closed and why it's slightly more work for the developers to maintain, but the "pipenv shell" command has too many drawbacks for me to use.

So now I'm wondering, would a pull request with a pipenv activate command (or setting so pipenv shell uses activate instead) be accepted or should I simply create an alias within my shell?

My personal reasons for wanting activate instead of shell:

  1. Backgrounded applications are unreachable. This is a dealbreaker for me because I generally have several backgrounded applications such as log tails running
  2. Breaks command history
  3. Current working directory is incorrect

As long as the virtualenv command keeps supporting a activate/deactivate command it shouldn't incur any extra maintenance for pipenv but I might be missing something

Just create your own alias. The activate idea has been proposed (and rejected) before.

Yeah too many platforms involved which is why we don鈥檛 use activate in the first place. You can add something to [scripts] to do something like pipenv run activate

I've simply written a little shell function called activate (similar to the virtualenv deactivate) which automatically activates the virtualenv by searching throug .venv and $WORKON_HOME.

It's part of my ever growing (and increasingly unreadable) package of shell scripts:
https://github.com/WoLpH/dotfiles/blob/fb8cadf59676328b6f8fe5623030251667fb56be/_zshrc#L293-L316

@WoLpH Your shell function activate looks useful, although it seems like it only works if PIPENV_VENV_IN_PROJECT is set to something. Am I right?

@Flimm you're right, I have that enabled by default so I forgot to mention that.

Here's a version that should work in all cases and sets slightly more environment variables:

activate(){
    activate_file=$(pipenv --venv)/bin/activate
    if [ -e "$activate_file" ]; then
        . $activate_file

        # the pipenv shell normally enables these as well
        export PYTHONDONTWRITEBYTECODE=1
        export PIPENV_ACTIVE=1

        if [ -f "${VIRTUAL_ENV}/.project" ]; then
            cd $(cat "${VIRTUAL_ENV}/.project")
        fi
        return
    fi
}

I used . $(pipenv --venv)/bin/activate to avoid execute "Permission denied" error

Was this page helpful?
0 / 5 - 0 ratings