команда workon не работает в Windows PowerShell для активации virtualenv

Я установил virtualenvwrapper-win, и когда я пытаюсь выполнить эту команду

workon <envname>

В CMD это работает, но не в Windows PowerShell.

В Windows PowerShell мне нужно выполнить Scripts\activate.ps1, а затем я получаю envname перед подсказкой.

Не могли бы вы сообщить мне, как заставить команду workon работать в PowerShell?


person Raj    schedule 14.08.2016    source источник


Ответы (6)


workon — это пакетный скрипт. Если вы запустите его из PowerShell, он запустится в новом дочернем процессе CMD, выполнив там свою работу, затем выйдите и вернитесь к командной строке PowerShell. Поскольку дочерние процессы не могут изменять своих родительских процессов, вы теряете все изменения, сделанные workon.bat, при возврате в PowerShell.

В основном у вас есть два варианта:

  • Перепишите workon.bat (и другие пакетные сценарии, которые он вызывает) в PowerShell.

  • Запустите workon.bat, не выходя из дочернего процесса CMD:

    & cmd /k workon <envname>
    

    Если вам просто нужен ярлык workon, который вы можете вызывать непосредственно из PowerShell, вы можете обернуть эту командную строку функцией и поместить определение функции в свой профиль PowerShell:

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

    Используйте здесь имя сценария с расширением, чтобы избежать бесконечной рекурсии.

person Ansgar Wiechers    schedule 14.08.2016
comment
Второй вариант не подходит, так как он уже не использует powershell. С таким же успехом можно было бы использовать cmd! - person pulsejet; 07.03.2018

Ответ Ансгара Вихерса технически работает, но он использует cmd, что означает, что вы в основном используете приглашение cmd из PowerShell и теряете дополнительные функции, предоставляемые PowerShell. Вы можете изменить приведенную выше функцию следующим образом:

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

Это позволит вам продолжать использовать команды PowerShell (которые не работают в cmd, такие как ls) в вашей виртуальной среде.

Это также предполагает, что ваши среды сохранены в .\Envs. Если они находятся в другом месте, то соответственно скорректируйте путь в функции или установите переменную окружения WORKON_HOME, см. ниже.

Если вы установили переменную окружения WORKON_HOME (что вы должны сделать!), вместо этого вы можете использовать:

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

Кроме того, если вы не пользователь Windows (как и я) и вам нужна помощь в том, где поместить эту функцию и как заставить ее загружаться при открытии PowerShell. Вот некоторые дополнительные ресурсы, которые мне помогли:

Фон:

Как написать модуль сценария PowerShell

Импорт модуля PowerShell

Как заставить PowerShell автоматически загружать ваш модуль при его запуске:

Как создать профиль PowerShell

Запустите PowerShell с загруженными модулями

person Erock    schedule 13.12.2017
comment
по умолчанию вы можете безопасно использовать переменную $HOME и $HOME\Envs\$env\Scripts\activate.ps1 - person userx; 26.11.2019

просто введите CMD в powershell, и он вызовет cmd, а затем продолжит работу.

person Gita    schedule 14.08.2020

Есть гораздо более простое решение! Просто перейдите в папку со сценариями Python, где существует файл workon.bat, создайте новый файл с именем workon.ps1 и добавьте в него следующую строку.

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

Вам может потребоваться изменить это соответствующим образом, если вы храните свои виртуальные окружения в другом месте, а также устанавливаете политику выполнения, чтобы разрешить сценарии. Теперь вы можете использовать workon как в cmd, так и в powershell, поскольку ps1 будет выполняться в powershell, а bat — в cmd.

Вы также можете проверить мой форк (полное раскрытие: я автор части powershell ) из virtualenvwrapper-win, который содержит несколько переписанных скриптов для powershell и должен работать как на CMD, так и на powershell. Если вы хотите скопировать-вставить, создайте два файла, workon.ps и `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
person pulsejet    schedule 02.03.2018
comment
Я думаю, что набрать & cmd /k workon <envname>, как сказал Ансгар Вихерс, намного проще, чем то, что вы предлагаете. - person ron_g; 07.03.2018
comment
@RonG Я считаю вторую часть этого ответа неправильной, поскольку она включает в себя переключение на cmd, что полностью исключает использование powershell. С тем же успехом я мог бы предложить вместо него использовать cmd, который сделал бы все за меня из коробки... - person pulsejet; 07.03.2018
comment
Я считаю, что мой ответ достаточно ясно дал понять, что второй пункт — это обходной путь, который запускается только из PowerShell, но работает в CMD. Кроме того, на момент публикации моего ответа не было кода PowerShell для virtualenv (отсюда и первый пункт). И FTR, все, что использует Invoke-Expression (например, ваш код), является неправильно по умолчанию. - person Ansgar Wiechers; 25.04.2019

У меня была аналогичная проблема. Исправлено это, выполнив некоторые из вышеуказанных шагов.

Список здесь:

  • установить как VirtualEnv, так и VirtualEnvWrapper-win
  • Установите для ExecutionPolicy значение RemoteSigned Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser.
  • Добавить путь среды «WORKON» в «каталог envs»
  • Теперь попробуйте команду «workon»
person Sagnik Saha    schedule 06.02.2020

Я столкнулся с той же проблемой, используя virtualenvwrapper в powershell в Windows10. Мне нравится ответ @Erock, но он переопределяет workon таким образом, что запуск workon без аргумента вызывает ошибку вместо отображения доступных сред. Вот мое решение.

function workon ($env) {
    if ($env) {
        & $env:WORKON_HOME\$env\Scripts\activate.ps1
    } else {
        Write-Host "Pass a name to activate one of the following virtualenvs:"
        Write-Host" ================================================================"
        Get-ChildItem $env:WORKON_HOME -Name
    }
}

Обратите внимание, что я уже установил переменную окружения WORKON_HOME.

person picklu    schedule 14.09.2020