当$env:path中定义了多个python可执行文件时,windows如何决定使用哪个python可执行程序



我在默认的powershell提示符中有几个python可执行文件,如where.exe python:所示

C:Program FilesInkscapebinpython.exe
C:Users921479AppDataLocalProgramsPythonPython310python.exe
C:Users921479AppDataLocalMicrosoftWindowsAppspython.exe

当我从这个powershell提示符启动python解释器时,它使用第一个可执行文件:

>>>python
Python 3.9.7 (default, Sep 22 2021, 08:12:47)  [GCC 10.3.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'C:\Program Files\Inkscape\lib\python39.zip', 'C:\Program Files\Inkscape\lib\python3.9', 'C:\Program Files\Inkscape\lib\python3.9\lib-dynload', 'C:\Users\921479', 'C:\Program Files\Inkscape\lib\python3.9\site-packages']

我不想从我的windows路径环境变量中删除C:Program FilesInkscapebin,因为我将inkscape命令行工具用于其他目的。然而,我更希望powershell使用python 3.10的本地安装作为我的";默认";python解释器。

当我检查$env:path变量时,看起来Inkscape文件夹是在python 3.10文件夹之后定义的。因此,它看起来像是用其他东西来解析python可执行文件:

>>>$env:path
C:Python310Scripts;C:Python310;C:Python39Scripts;C:Python39;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;C:WindowsSystem32OpenSSH;C:ProgramDatachocolateybin;C:Users921479AppDataLocalSumatraPDF;C:Program FilesGitcmd;C:texlive2021binwin32;C:Program Files (x86)PDFtk Serverbin;C:Program Files (x86)Lua5.1;C:Program Files (x86)Lua5.1clibs;C:Program FilesInkscapebin;C:Program Filesdotnet;C:Users921479AppDataLocalProgramsPythonPython310Scripts;C:Users921479AppDataLocalProgramsPythonPython310;C:Users921479AppDataLocalMicrosoftWindowsApps;C:Users921479.dotnettools

powershell/windows如何决定使用哪个python可执行文件?如何修改?

Thomas Weller的有用回答提供了很好的一般信息。

至于在PowerShell中使用直接调用的可执行文件(仅限名称)(包括或不包括其文件扩展名):

  • $env:Path中列出的目录中按顺序查找仅由名称指定的可执行文件,并使用第一个匹配目录中的可执行程序

    • 请注意,PowerShell与cmd.exe不同,从设计上讲,作为一种安全功能,不会仅按名称执行位于当前目录中的可执行文件,并要求您通过在名称前加.(或使用完整路径)来明确表示调用此类程序的意图。

    • 换句话说:如果python.exe可执行文件恰好出现在当前目录中,则提交python:

      CCD_ 11中的
      • 将执行it
      • 而PowerShell将忽略它并仅查阅CCD_ 12

这个与您的经验是一致的:即使$env:Path变量的C:Python310C:Python39的条目在C:Program FilesInkscapebin之前,但它们并不包含python.exe可执行文件,正如where.exe命令的输出所暗示的那样,这表明唯一相关的目录是C:Program FilesInkscapebinC:Users921479AppDataLocalProgramsPythonPython310,以及C:Users921479AppDataLocalMicrosoftWindowsApps按顺序反映在您的$env:Path值中。

等效于PowerShell中的where.exe调用(PowerShell从不在当前目录中列出任何匹配项除外),使用Get-Commandcmdlet:

Get-Command python -All

省略-All将只显示命令的有效形式,即在调用时实际使用的形式。


如何修改?

再次从PowerShell的角度:根据您的需要,您有两种选择:

  • 您可以选择性地仅为当前PowerShell会话修改$env:PATH,这将将修改后的查找顺序限制为该会话和从该会话启动的进程。独立进程(如单独的cmd.exe会话)不会受到影响:

    # Simply *prepend* the desired directory to $env:Path
    $env:Path = 'C:Users921479AppDataLocalProgramsPythonPython310;' + $env:Path
    
  • 如果要将修改后的查找顺序限制为仅PowerShell代码,即以交互或从PowerShell脚本或函数提交的pythonpython.exe调用,则可以定义别名

    New-Alias python.exe C:Users921479AppDataLocalProgramsPythonPython310python.exe
    New-Alias python python.exe
    

在这两种情况下,如果您想自动实现这些修改,对于未来的所有PowerShell会话,请将这些语句添加到$PROFILE文件中。

Windows将执行的内容并非微不足道,因为它可能取决于所使用的API。

其中之一是CreateProcessW:

  1. 加载应用程序的目录
  2. 父进程的当前目录
  3. 32位Windows系统目录。使用GetSystemDirectory函数获取此目录的路径
  4. 16位Windows系统目录。没有任何函数可以获取此目录的路径,但会对其进行搜索。此目录的名称为System
  5. Windows目录。使用GetWindowsDirectory函数获取此目录的路径
  6. PATH环境变量中列出的目录。请注意,此函数不会搜索App Paths注册表项指定的每个应用程序路径。要在搜索序列中包含每个应用程序的路径,请使用ShellExecute函数

自Windows Vista以来,环境变量%NoDefaultCurrentDirectoryInExePath%配置是否应搜索当前目录(来源:MSDN)。

此外:如果您只是在没有扩展的情况下运行python,则使用环境变量%PathExt%来查找可执行扩展。(来源:MSDN)。

PATHEXT变量的默认值为:.COM;。EXE;。蝙蝠;。CMD;。VBS;。VBE;。JS;。JSE;。WSF;。WSH;。MSC-

解决此类问题的一个好工具是SysInternal Process Monitor。为";路径包含python";(不是python.exe),您将看到确切的搜索顺序。它将报告";没有这样的文件";用于不包含Python可执行文件的目录。

另请注意:DLL的搜索顺序可能不同。

相关内容