workon command doesn't work in Windows PowerShell to activate virtualenv

偶尔善良 提交于 2019-12-06 01:37:21

问题


I have installed virtualenvwrapper-win and when I try this command

workon <envname>

In CMD it works, but not in Windows PowerShell.

In Windows PowerShell I have to do Scripts\activate.ps1 and then I get the envname before the prompt.

Can you please let me know how can I make workon command working in PowerShell?


回答1:


workon is a batch script. If you run it from PowerShell it's launched in a new CMD child process, doing its thing there, then exit and return to the PowerShell prompt. Since child processes can't modify their parent you lose all modifications made by workon.bat when you return to PowerShell.

You basically have two options:

  • Rewrite workon.bat (and the other batch scripts it calls) in PowerShell.

  • Run workon.bat in without exiting from the CMD child process:

    & cmd /k workon <envname>
    

    If you just want a shortcut workon that you can call directly from PowerShell you can wrap that commandline in a function and put the function definition into your PowerShell profile:

    function workon($environment) {
      & cmd /k workon.bat $environment
    }
    

    Use the scriptname with extension here to avoid infinite recursion.




回答2:


The answer by Ansgar Wiechers technically works but it uses cmd which means you are basically using the cmd prompt from within PowerShell and you lose the additional functionality provided by PowerShell. You can modify the function above to the following:

function workon ($env) { & .\Envs\$env\Scripts\activate.ps1 }

This will allow you to continue to use PowerShell commands (that do not work in cmd such as ls) in your virtual environment

This also assumes that your environments are saved in .\Envs. If they are elsewhere, then adjust the path in the function accordingly.

Additionally, if you are not a Windows user (like me) and need help on where to put that function and how to get it to load when you open PowerShell. Here are some additional resources that helped me:

Background:

How to Write a PowerShell Script Module

Importing a PowerShell Module

How to get PowerShell to autoload your module when it starts:

How to Create a PowerShell Profile

Start PowerShell with modules loaded




回答3:


There is a much simpler solution! Just go to your python scripts folder, where the workon.bat file exists and create a new file named workon.ps1 and add the following line to it

iex ("~\Envs\" + $args[0] + "\Scripts\activate.ps1")

You many need to change this appropriately if you store your virtualenvs elsewhere and also set the Execution Policy to allow scripts. Now you can use workon in both cmd and powershell, since the ps1 will be executed in powershell and bat in cmd.

You can also check out my fork (full disclosure: I'm the author of the powershell part) of virtualenvwrapper-win, which contains some rewritten scripts for powershell and should work on both CMD and powershell. If you want to copy-paste, create two files, workon.ps and `cdproject.

workon.ps1:

if (-not (Test-Path env:WORKON_HOME))
{
    $WORKON_HOME = '~\Envs'
} else {
    $WORKON_HOME = ($env:WORKON_HOME).Replace('"','')
}

if (-not (Test-Path env:VIRTUALENVWRAPPER_PROJECT_FILENAME)) {
    $VIRTUALENVWRAPPER_PROJECT_FILENAME = '.project'
} else {
    $VIRTUALENVWRAPPER_PROJECT_FILENAME = ($env:VIRTUALENVWRAPPER_PROJECT_FILENAME).Replace('"','')
}

if ($args.length -eq 0) {
    echo "Pass a name to activate one of the following virtualenvs:"
    echo ==============================================================================
    (Get-ChildItem -Path $WORKON_HOME).Name
    return
}

$VENV = $args[0]

if (!(Test-Path -Path ("$($WORKON_HOME)\$($VENV)"))) {
    echo ("virtualenv $($VENV) does not exist")
    echo "Create it with 'mkvirtualenv $($VENV)'"
    return
}

if (!(Test-Path -Path ("$($WORKON_HOME)\$($VENV)\Scripts\activate.ps1") ))  {
    echo "$($WORKON_HOME)$($VENV)"
    echo "doesn't contain a virtualenv (yet)."
    echo "Create it with 'mkvirtualenv $($VENV)'"
    return
}

iex ("$($WORKON_HOME)\$($VENV)\Scripts\activate.ps1")

if (Test-Path -Path ("$($WORKON_HOME)\$($VENV)\$($VIRTUALENVWRAPPER_PROJECT_FILENAME)")) {
    iex "cdproject"
}

cdproject.ps1:

function Show-Usage {
    echo ""
    echo  "switches to the project dir of the activated virtualenv"
}

if (-not (Test-Path env:VIRTUAL_ENV)) {
    echo ""
    echo "a virtualenv must be activated"
    Show-Usage
    return
}

if (-not (Test-Path env:VIRTUALENVWRAPPER_PROJECT_FILENAME)) {
    $VIRTUALENVWRAPPER_PROJECT_FILENAME = '.project'
} else {
    $VIRTUALENVWRAPPER_PROJECT_FILENAME = ($env:VIRTUALENVWRAPPER_PROJECT_FILENAME).Replace('"','')
}

if (-not (Test-Path "$($env:VIRTUAL_ENV)\$($VIRTUALENVWRAPPER_PROJECT_FILENAME)")) {
    echo ""
    echo "No project directory found for current virtualenv"
    Show-Usage
    return
}


$ENVPRJDIR = Get-Content "$($env:VIRTUAL_ENV)\$($VIRTUALENVWRAPPER_PROJECT_FILENAME)" -First 1

# If path extracted from file contains env variables, the system will not find the path.
# TODO: Add this functionality

cd $ENVPRJDIR


来源:https://stackoverflow.com/questions/38944525/workon-command-doesnt-work-in-windows-powershell-to-activate-virtualenv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!