从另一个 Python 安装导入的模块
Module being imported from another Python install
我 运行 在 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:按照 ham-sandwich 的建议,使用 pyvenv 时会发生同样的事情。
唯一让我觉得奇怪的是你是运行
D:\PyVirtualEnvs\example_py34\Scripts\activate.bat
在 powershell 中有激活时。ps1。不知道这个有没有兼容性问题
如果您 运行 来自 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
并传播环境变量更改。
我发现了这种行为的原因。 PYTHONPATH 环境变量被设置为 Python 安装在机器上的一个不寻常的位置。
根据the documentation,当在当前目录中找不到模块时,PYTHONPATH 被用作导入位置。
When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:
- the directory containing the input script (or the current directory).
- PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
- the installation-dependent default.
由于某些原因,activate/deactivate 脚本没有 set/unset PYTHONPATH。它确实设置了 PYTHONHOME,但这似乎并不影响导入。这感觉像是 virtualenv 和 pyvenv 中的错误(我都试过了)。
原来的 activate.bat 脚本改变了一个 "set" 变量,它不影响 $env:PYTHONPATH。 Activate.ps1 尝试将原始 PYTHONPATH 保存在一个变量中,将其设置为虚拟环境目录,然后在停用时恢复原始 PYTHONPATH。这些都不再起作用,可能是由于 Powershell 或 Python 更新。
我们的解决方案是修改激活和停用脚本(PoSh 或 bat)以在两个硬编码值之间切换 PYTHONPATH。
我 运行 在 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:按照 ham-sandwich 的建议,使用 pyvenv 时会发生同样的事情。
唯一让我觉得奇怪的是你是运行
D:\PyVirtualEnvs\example_py34\Scripts\activate.bat
在 powershell 中有激活时。ps1。不知道这个有没有兼容性问题
如果您 运行 来自 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
并传播环境变量更改。
我发现了这种行为的原因。 PYTHONPATH 环境变量被设置为 Python 安装在机器上的一个不寻常的位置。
根据the documentation,当在当前目录中找不到模块时,PYTHONPATH 被用作导入位置。
When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:
- the directory containing the input script (or the current directory).
- PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
- the installation-dependent default.
由于某些原因,activate/deactivate 脚本没有 set/unset PYTHONPATH。它确实设置了 PYTHONHOME,但这似乎并不影响导入。这感觉像是 virtualenv 和 pyvenv 中的错误(我都试过了)。
原来的 activate.bat 脚本改变了一个 "set" 变量,它不影响 $env:PYTHONPATH。 Activate.ps1 尝试将原始 PYTHONPATH 保存在一个变量中,将其设置为虚拟环境目录,然后在停用时恢复原始 PYTHONPATH。这些都不再起作用,可能是由于 Powershell 或 Python 更新。
我们的解决方案是修改激活和停用脚本(PoSh 或 bat)以在两个硬编码值之间切换 PYTHONPATH。