【问题标题】:Module being imported from another Python install从另一个 Python 安装导入的模块
【发布时间】:2015-12-07 18:51:06
【问题描述】:

我正在 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 中的错误还是我遗漏了什么?

编辑:会不会和this question有关?

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

【问题讨论】:

  • 也许是一个愚蠢的问题,但你确定你已经激活了 venv 吗? venv\Scripts\activate.bat
  • 是的,在上面第三个代码框的顶部。话虽如此,在验证它是否有效时没有视觉反馈。
  • 是否有理由使用 virtualenv 而不是 pyvenv? docs.python.org/3/library/venv.html#module-venv
  • @ham-sandwich - 哦,这对我来说是个新闻。感谢您提供来自相关 PEP 的链接,听起来不错。但是,我上面的问题似乎比 virtualenvs 更深入;我仍然对 3.4 从 3.3 导入一些东西感到惊讶,并且想知道为什么。
  • 我们的一个虚拟环境也是 2.7,我认为 pyenv 是 3.3+

标签: python powershell python-3.4 windows-server-2012 python-venv


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢,好点子,但我刚刚试了一下,得到了相同的结果。
【解决方案2】:

如果您从 PowerShell(批处理文件)运行 cmd.exe shell 脚本,PowerShell 会生成一个 cmd.exe 实例来运行脚本(批处理文件)。如果批处理文件设置了环境变量,则它们仅存在于生成的 cmd.exe 实例中。一旦该实例终止(即脚本结束时),环境变量就不会传播到调用进程(在本例中为 PowerShell)。这是设计使然。

如果要传播环境变量,可以在PowerShell中使用以下Invoke-CmdScript函数:

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 并传播环境变量更改。

【讨论】:

  • 谢谢,我不知道。但是,Invoke-CmdScript 函数似乎吞噬了 python 的所有输出,即使在交互式 shell 中也是如此。如果我按照建议运行激活然后调用 python 命令它仍然是 django 的错误版本,如果我尝试 Invoke-CmdScript python.exe -c 导入失败。
  • 大概我需要通过一个批处理文件调用来运行我想要的所有东西,以在 activate 和 python 调用之间保留这些环境变量。
  • 你不会使用那个函数来运行python;您只会使用它来执行activate.bat 脚本并传播它设置的环境变量。请注意,如另一个答案中所述,有一个专门针对 PowerShell 的 activate.ps1
  • 对不起,交叉,cmets。使用 Invoke-CmdScript 运行 activate.bat (似乎很好)。如上所述运行 python 调用(仍然是 django 1.6.5)。与 activate.ps1 相同
  • 我的答案是特定于运行cmd.exe shell 脚本(批处理文件)并将其环境变量传播到 PowerShell。我不使用 python,所以我无法评论你正在做的其他事情。在我看来,您需要更好地定义您的具体问题。
【解决方案3】:

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

根据the documentation,当在当前目录中找不到模块时,使用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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-18
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 2018-04-23
    • 2015-07-26
    相关资源
    最近更新 更多