fikunmi
fikunmi

Reputation: 23

Computer can't find installed libraries

I use VSCode Anytime I install a python library, I get this notification:

WARNING: The scripts auto-py-to-exe.exe and autopytoexe.exe are installed in 'C:\Users\PC\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\Scripts' which is not on PATH

But I've added that to path. If I run:

echo $env:PATH

I get

C:\Users\PC\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\Scripts:C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Users\PC\AppData\Local\Microsoft\WindowsApps;C:\Users\PC\AppData\Local\Programs\Microsoft VS Code\bin;C:\texlive\2023\bin\windows

suggesting that I've added said path.

I'm confused because I can't run packages from the CLI directly, even though importing them works.

I added the path manually and I've tried removing it but that doesn't work. Any ideas on what to do?

Upvotes: 1

Views: 109

Answers (2)

mklement0
mklement0

Reputation: 439417

Your own solution is effective in principle - ; is the required separator on Windows - except that your statement isn't valid PowerShell code, and that \ chars. don't need escaping as \\ in PowerShell; also, you can express the new directory path more generically using the LOCALAPPDATA environment variable; therefore:

$newDir = "$env:LOCALAPPDATA\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\Scripts"
$env:PATH = "$newDir;$env:PATH" 

The above modifies $env:PATH only for the current session (process).
To also persist this change on Windows - so that future sessions see it too:

  • Interactively, run sysmd.cpl, select the Advanced tab, and click on Environment Variables..., then add the value of $newDir to the desired scope; since your directory path is user-specific, add it to the User variables for <username> list.

  • Programmatically, this is surprisingly difficult to do robustly:

    • If you don't mind converting the original REG_EXPAND_SZ definition to a static REG_SZ one, you can use [Environment]::SetEnvironmentVariable() (to target the machine-level definition of the variable, change 'User' to 'Machine', but not that doing so requires elevation (running as administrator):

      [Environment]::SetEnvironmentVariable(
        'PATH',
        ($newDir + ';' + [Environment]::GetEnvironmentVariable('PATH', 'User')), 
        'User'
      ) 
      
    • While this typically has no ill effects, it can; see this answer for background information and a robust alternative; this answer wraps the robust alternative in a helper function, Add-Path, and explains why setx.exe should be avoided for PATH updates.

    • A simpler programmatic alternative, which also works on Unix-like platforms, is to add the above statements to your $PROFILE file, but note that only PowerShell sessions and programs launched from them will then see the updated PATH, and that profile-loading can be suppressed by launching a PowerShell session via the -NoProfile CLI parameter (the PowerShell CLI (powershell.exe -NoProfile for Windows PowerShell, pwsh -NoProfile for PowerShell (Core) 7+)

Note that .NET cannot offer APIs for persistent environment-variable definitions on Unix-like platforms, because there's no unified mechanism across all of them.


Cross-platform background information on the PATH environment variable:

  • The platform-specific separator used in the list of directory paths stored in the special PATH environment variable is:

    • ; on Windows
    • : on Unix-like platforms
  • In cross-platform scripting, make changes to PATH as follows in PowerShell:

    • Use $env:PATH - all uppercase - because environment-variable access is case-sensitive on Unix-like platforms, and the special variable's name is indeed PATH there.

      • On Windows, the official name is Path, but because environment-variable access is case-insensitive, any case variation and therefore also PATH works.
    • Use the - confusingly named - [System.IO.Path]::PathSeparator property to get the platform-native separator.

    • In forming directory paths to add, use the platform-native file-system path separator, which .NET reflects in the - equally unfortunately named - [System.IO.Path]::DirectorySeparatorChar property.

      • PowerShell's Join-Path cmdlet and .NET's [System.IO.Path]::Combine() method, when given components of a path, implicitly use the platform-native separator, which is \ on Windows, and / on Unix-like platforms.

        • Note that \ has no special meaning in PowerShell (and neither in cmd.exe) so there is no need to represent literal \ characters as \\ (however, in the context of file-system paths, such accidentally duplicated separators are generally still accepted).
      • On Windows, you could alternatively use / as well, which is safe to use in the context of PATH as well as PowerShell-native commands.

        • .NET reflects this fact via the [System.IO.Path]::AltDirectorySeparatorChar property

        • However, programs / scripts examining $env:PATH for existing entries are likely to assume \, so it's best to use the platform-native separator.

        • Also, generally speaking, there are still Windows contexts where / doesn't work, such as in cmd.exe and COM APIs.

    • Generally, aim to express your directory paths in terms of environment / well-known directories, to be resolved to literals paths at the time of adding entries:

      • E.g., the C:\Users\PC\AppData\Local part of your path could be replaced with environment variable $env:LOCALAPPDATA

      • However, for cross-platform use it's best to use platform-agnostic abstractions, as provided - within limits - by [System.Environment]::GetFolderPath()

        • E.g., the platform-agnostic equivalent of the above is:

          [Environment]::GetFolderPath('LocalApplicationData')
          
      • Since use of [System.Environment]::GetFolderPath() isn't very PowerShell-friendly, GitHub issue #6966 asks for surfacing known folders platform-agnostically via a separate namespace / provider, e.g. $sf:LocalApplicationData (sf standing for special folder).

Upvotes: 1

fikunmi
fikunmi

Reputation: 23

The error was in the path I specified. I was sure everyone asked me to use a colon but at @buran 's suggestion, I changed the colon right before "${env:PATH}" to a semi-colon and that was it.

old path:

 "PATH": "C:\\Users\\PC\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python311\\Scripts:${env:PATH}"

new path:

"PATH": "C:\\Users\\PC\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python311\\Scripts;${env:PATH}"

Upvotes: 0

Related Questions