Module being imported from another Python install

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-08 10:48:43

问题


I'm running multiple installs of Python on Windows Server 2012. I can probably find a way to work around this, but I'm curious as to what is going on. I'm wary about radically changing the installs in case I break other people's Python scheduled tasks that I may not be aware of.

(All the code boxes below are PowerShell).

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

Although this Python 3.4 install doesn't have Django installed, it appears to pick up the version from the Python 33x86 install. Is that normal?

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

I've created a Python virtualenv based on Python 3.4 and installed Django 1.8.4 in it. Doing a "pip list" confirms that it is installed correctly:-

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)

However, when I import within that virtualenv, I get Django version 1.6.5:-

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

Is this a bug in virtualenv or am I missing something?

EDIT: Could it be related to this question?

EDIT2: The same thing happens when using pyvenv, as suggested by ham-sandwich.


回答1:


The only thing that looks strange to me is that you are running

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

in powershell when a there is a activate.ps1. I don't know if there are compatibility issues with this.




回答2:


If you run a cmd.exe shell script from PowerShell (a batch file), PowerShell spawns an instance of cmd.exe to run the script (batch file). If the batch file sets environment variables, they exist only in the spawned cmd.exe instance. Once that instance terminates (i.e., when the script ends), the environment variables do not propagate to the calling process (PowerShell, in this case). This is by design.

If you want to propagate environment variables, you can use the following Invoke-CmdScript function in 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
  }
}

Some more information about this in the following article:

Windows IT Pro: Take Charge of Environment Variables in PowerShell

In your case, you would run:

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

This will spawn activate.bat and propagate the environment variable changes.




回答3:


I've discovered the reason for this behaviour. The PYTHONPATH environment variable was set to a Python installation at an unusual location on the machine.

According to the documentation, PYTHONPATH is used as the import location when the module is not found in the current directory.

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.

For some reason PYTHONPATH is not set/unset by the activate/deactivate scripts. It does set PYTHONHOME, but this doesn't seem to affect imports. This feels like a bug in virtualenv and pyvenv (I tried both).

The original activate.bat scripts change a "set" variable, which doesn't affect the $env:PYTHONPATH. Activate.ps1 attempts to save the original PYTHONPATH in a variable, set it to the virtual environment directory, then on deactivate, restore the original PYTHONPATH. Neither of these work anymore, possibly due to a Powershell or Python update.

The solution for us is to modify the activate and deactivate scripts (PoSh or bat) to switch the PYTHONPATH between two hard-coded values.



来源:https://stackoverflow.com/questions/32519580/module-being-imported-from-another-python-install

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!