0

Я запускаю несколько установок Python на Windows Server 2012. Возможно, я найду способ обойти это, но мне любопытно, что происходит. Я опасаюсь радикально менять установки в случае, если я нарушу запланированные задачи Python других людей, о которых я, возможно, и не подозреваю.Модуль, импортируемый из другой установки Python

(Все кодовые окна ниже - PowerShell).

PS C:\> C:\Python34\Scripts\pip.exe list 
jdcal (1.0) 
pip (7.1.2) 
setuptools (12.0.5) 
virtualenv (13.1.2) 

Хотя Python 3.4 установить не установлен Django, по-видимому подобрать версию из Python 33x86 установки. Это нормально?

PS C:\> C:\Python34\python.exe -c "import django; print(django.get_version())" 
1.6.5 
PS C:\> C:\Python33x86\python.exe -c "import django; print(django.get_version())" 
1.6.5 

Я создал виртуальный виртуальный Python на основе Python 3.4 и установлен в нем Django 1.8.4. Выполнение «пип» список подтверждает, что он правильно установлен: -

PS C:\> D:\PyVirtualEnvs\example_py34\Scripts\activate.bat 
PS C:\> D:\PyVirtualEnvs\example_py34\Scripts\pip.exe list | Select-String "Django " 
Django (1.8.4) 

Однако, когда я импортировать в этом virtualenv, я получаю Django версии 1.6.5: -

PS C:\> D:\PyVirtualEnvs\example_py34\Scripts\python.exe -c "import django; print(django.get_version())" 
1.6.5 

Является ли это ошибка в virtualenv или я чего-то не хватает?

EDIT: Не может быть связано с this question?

EDIT2: То же самое происходит при использовании pyvenv, как предложено ветчиной-сэндвичем.

+0

Может быть, глупый вопрос, но вы уверены, что активировали вен? 'venv \ Scripts \ activate.bat' –

+0

Да, в верхней части 3-го кода выше. Говоря это, нет визуальной обратной связи, когда делаете это, чтобы убедиться, что она сработала. –

+0

Есть ли причина для использования virtualenv, а не pyvenv? https://docs.python.org/3/library/venv.html#module-venv –

ответ

0

Я обнаружил причину такого поведения. Переменная среды PYTHONPATH была установлена ​​на установку Python в необычном месте на машине.

Согласно the documentation, PYTHONPATH используется в качестве места импорта, когда модуль не найден в текущем каталоге.

Когда импортируется модуль со спамом, интерпретатор сначала ищет встроенный модуль с этим именем. Если он не найден, он ищет файл с именем spam.py в списке каталогов, заданных переменной sys.path. sys.path инициализируется из этих мест:

  • каталог, содержащий входной скрипт (или текущий каталог).
  • PYTHONPATH (список имен каталогов, с тем же синтаксисом, что и переменная оболочки PATH).
  • зависит от установки по умолчанию.

По какой-то причине PYTHONPATH не установлена ​​/ снята с охраны с помощью включения/отключения скриптов. Он устанавливает PYTHONHOME, но это, похоже, не влияет на импорт. Это похоже на ошибку в virtualenv и pyvenv (я пробовал оба).

Исходные скрипты activate.bat изменяют переменную «set», которая не влияет на $ env: PYTHONPATH. Activate.ps1 пытается сохранить исходный PYTHONPATH в переменной, установить его в каталог виртуальной среды, затем отключить, восстановить исходный PYTHONPATH. Ни одна из них больше не работает, возможно, из-за обновления Powershell или Python.

Решение для нас - изменить активировать и деактивировать скрипты (PoSh или bat), чтобы переключить PYTHONPATH между двумя жестко заданными значениями.

1

Единственное, что выглядит странно для меня является то, что вы работаете

D:\PyVirtualEnvs\example_py34\Scripts\activate.bat 

в PowerShell, когда есть activate.ps1. Я не знаю, есть ли проблемы совместимости с этим.

+0

Спасибо, хорошо, но я просто попробовал и получил те же результаты. –

1

Если вы запускаете сценарий оболочки cmd.exe из PowerShell (пакетный файл), PowerShell запускает экземпляр cmd.exe для запуска скрипта (пакетного файла). Если командный файл задает переменные окружения, они существуют только в порожденном экземпляре cmd.exe. Как только этот экземпляр завершается (то есть, когда скрипт заканчивается), переменные среды не распространяются на вызывающий процесс (в этом случае PowerShell). Это по дизайну.

Если вы хотите распространять переменные окружения, вы можете использовать следующую Invoke-CmdScript функцию в PowerShell:

function Invoke-CmdScript { 
    param(
    [String] $scriptName 
) 
    $cmdLine = """$scriptName"" $args & set" 
    & $Env:SystemRoot\system32\cmd.exe /c $cmdLine | 
    Select-String '^([^=]*)=(.*)$' | ForEach-Object { 
    $varName = $_.Matches[0].Groups[1].Value 
    $varValue = $_.Matches[0].Groups[2].Value 
    Set-Item Env:$varName $varValue 
    } 
} 

Некоторые больше информации об этом в следующей статье:

Windows IT Pro: Take Charge of Environment Variables in PowerShell

В вашей в случае, вы будете запускать:

PS C:\> Invoke-CmdScript D:\PyVirtualEnvs\example_py34\Scripts\activate.bat 

Это будет порождать activate.bat и распространять изменения переменных среды.

+0

Спасибо, я этого не знал. Однако функция Invoke-CmdScript, по-видимому, проглатывает весь вывод из python, даже в интерактивной оболочке. Если я запустил активировать, как было предложено, тогда вызов команды python по-прежнему является неправильной версией django, если я пытаюсь выполнить Invoke-CmdScript python.exe, сбой -c невозможен. –

+0

Предположительно мне нужно было запустить все, что я хотел, с помощью одного вызова пакетного файла, чтобы сохранить эти переменные среды между вызовами активации и вызова python. –

+0

Вы не использовали бы эту функцию для запуска python; вы должны использовать его только для запуска скрипта 'activate.bat' и распространения переменных среды, которые он устанавливает. Обратите внимание, что для PowerShell определен параметр 'activate.ps1', как указано в другом ответе. –

Смежные вопросы