0

我在 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 3.4 的 Python virtualenv 并在其中安装了 Django 1.8.4。执行“pip list”确认它已正确安装:-

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 中的错误还是我错过了什么?

编辑:这可能与这个问题有关吗?

EDIT2:使用pyvenv时也会发生同样的事情,正如 ham-sandwich 所建议的那样。

4

3 回答 3

1

唯一让我觉得奇怪的是你在跑步

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

在powershell中,当有一个activate.ps1时。我不知道这是否存在兼容性问题。

于 2015-09-11T12:54:49.447 回答
1

如果cmd.exe从 PowerShell(批处理文件)运行 shell 脚本,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:负责 PowerShell 中的环境变量

在您的情况下,您将运行:

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

这将产生activate.bat并传播环境变量更改。

于 2015-09-11T14:51:14.673 回答
0

我发现了这种行为的原因。PYTHONPATH 环境变量设置为机器上不寻常位置的 Python 安装。

根据文档,当在当前目录中找不到模块时,使用 PYTHONPATH 作为导入位置。

当导入名为 spam 的模块时,解释器首先搜索具有该名称的内置模块。如果没有找到,它会在变量 sys.path 给出的目录列表中搜索名为 spam.py 的文件。sys.path 从这些位置初始化:

  • 包含输入脚本的目录(或当前目录)。
  • PYTHONPATH(目录名称列表,与 shell 变量 PATH 具有相同的语法)。
  • 安装相关的默认值。

由于某种原因,激活/停用脚本未设置/取消设置 PYTHONPATH。它确实设置了 PYTHONHOME,但这似乎不会影响导入。这感觉就像 virtualenv 和 pyvenv 中的错误(我都试过了)。

原始的 activate.bat 脚本更改了一个“set”变量,这不会影响 $env:PYTHONPATH。Activate.ps1 尝试将原始 PYTHONPATH 保存在一个变量中,将其设置为虚拟环境目录,然后在停用时恢复原始 PYTHONPATH。这些都不再起作用,可能是由于 Powershell 或 Python 更新。

我们的解决方案是修改激活和停用脚本(PoSh 或 bat)以在两个硬编码值之间切换 PYTHONPATH。

于 2015-09-15T09:28:34.160 回答