Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Newest 3.12 install on windows misses pip #117505

Closed
EDM115 opened this issue Apr 3, 2024 · 13 comments
Closed

[BUG] Newest 3.12 install on windows misses pip #117505

EDM115 opened this issue Apr 3, 2024 · 13 comments
Labels
OS-windows topic-ensurepip type-bug An unexpected behavior, bug, or error

Comments

@EDM115
Copy link

EDM115 commented Apr 3, 2024

Bug report

Bug description:

I recently did a fresh python installation, from python.org (https://www.python.org/ftp/python/3.12.2/python-3.12.2-amd64.exe)
I did installed it on an "uncommon" directory (D:\EDM115\Programmes\Python312\), but this had never caused any issue in the past.
The main issue is that the Scripts folder was simply empty, meaning that no pip command worked. I verified that the pip checkbox was checked, tried to repair and later redo the install, only to face the same issues.
What fixed it was to run py -m ensurepip --upgrade and later rename D:\EDM115\Programmes\Python312\Scripts\pip3.exe to D:\EDM115\Programmes\Python312\Scripts\pip.exe, but I believe that it should be done automatically

CPython versions tested on:

3.12

Operating systems tested on:

Windows

Linked PRs

@EDM115 EDM115 added the type-bug An unexpected behavior, bug, or error label Apr 3, 2024
@zooba
Copy link
Member

zooba commented Apr 3, 2024

Can you zip up all the Python*.log files in your %TEMP% directory and attach them for us? Those should show why the install failed.

@EDM115
Copy link
Author

EDM115 commented Apr 4, 2024

Issue 117505 logs.zip
@zooba here you go
note that I tried several install/repair so that's why there's so many 😅

@zooba
Copy link
Member

zooba commented Apr 4, 2024

Well this is a very interesting case:

CAQuietExec64:  ERROR: Exception:
CAQuietExec64:  Traceback (most recent call last):
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\cli\base_command.py", line 180, in exc_logging_wrapper
CAQuietExec64:      status = run_func(*args)
CAQuietExec64:               ^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\cli\req_command.py", line 245, in wrapper
CAQuietExec64:      return func(self, options, args)
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\commands\install.py", line 324, in run
CAQuietExec64:      session = self.get_default_session(options)
CAQuietExec64:                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\cli\req_command.py", line 95, in get_default_session
CAQuietExec64:      self._session = self.enter_context(self._build_session(options))
CAQuietExec64:                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\cli\req_command.py", line 122, in _build_session
CAQuietExec64:      session = PipSession(
CAQuietExec64:                ^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\network\session.py", line 342, in __init__
CAQuietExec64:      self.headers = user_agent()
CAQuietExec64:                                   ^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\network\session.py", line 175, in user_agent
CAQuietExec64:      setuptools_dist = get_default_environment().get_distribution("setuptools")
CAQuietExec64:                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\importlib\_envs.py", line 189, in get_distribution
CAQuietExec64:      return next(matches, None)
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\importlib\_envs.py", line 184, in <genexpr>
CAQuietExec64:      matches = (
CAQuietExec64:                ^
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\base.py", line 626, in iter_all_distributions
CAQuietExec64:      for dist in self._iter_distributions():
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\importlib\_envs.py", line 181, in _iter_distributions
CAQuietExec64:      yield from finder.find_linked(location)
CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\importlib\_envs.py", line 96, in find_linked
CAQuietExec64:      if not path.is_dir():
CAQuietExec64:             ^^^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\pathlib.py", line 875, in is_dir
CAQuietExec64:      return S_ISDIR(self.stat().st_mode)
CAQuietExec64:                     ^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\pathlib.py", line 840, in stat
CAQuietExec64:      return os.stat(self, follow_symlinks=follow_symlinks)
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:  OSError:  Le chemin d’accès ne peut pas être parcouru car il contient un point de montage non approuvé: 'C:\\Program Files\\Csound6_x64\\bin'
CAQuietExec64:  Traceback (most recent call last):
CAQuietExec64:    File "<frozen runpy>", line 198, in _run_module_as_main
CAQuietExec64:    File "<frozen runpy>", line 88, in _run_code
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\ensurepip\__main__.py", line 5, in <module>
CAQuietExec64:      sys.exit(ensurepip._main())
CAQuietExec64:               ^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\ensurepip\__init__.py", line 284, in _main
CAQuietExec64:      return _bootstrap(
CAQuietExec64:             ^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\ensurepip\__init__.py", line 200, in _bootstrap
CAQuietExec64:      return _run_pip(, additional_paths)
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\ensurepip\__init__.py", line 101, in _run_pip
CAQuietExec64:      return subprocess.run(cmd, check=True).returncode
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\subprocess.py", line 571, in run
CAQuietExec64:      raise CalledProcessError(retcode, process.args,
CAQuietExec64:  subprocess.CalledProcessError: Command ' + sys.path\nsys.argv = '\nrunpy.run_module("pip", run_name="__main__", alter_sys=True)\n']' returned non-zero exit status 2.
CAQuietExec64:  Error 0x80070001: Command line returned an error.
CAQuietExec64:  Error 0x80070001: QuietExec64 Failed
CAQuietExec64:  Error 0x80070001: Failed in ExecCommon64 method

The exception OSError: Le chemin d’accès ne peut pas être parcouru car il contient un point de montage non approuvé: 'C:\\Program Files\\Csound6_x64\\bin' translates as "The path cannot be traversed because it contains an untrusted mount point".

It appears that Csound6_x64's installer overrides the global PYTHONPATH environment variable, and while we tell Python to ignore this when we run the ensurepip command, it looks like they start a new child process which doesn't ignore it. And because it's running as an installer, it gets blocked, probably as part of a security fix in Windows (this is why it works when you run ensurepip yourself).

Probably we can just make ensurepip clear PYTHONPATH itself before launching any new copies of Python, though there may be a deeper fix that's possible in pip to also avoid this issue.

@zooba
Copy link
Member

zooba commented Apr 4, 2024

I also need to take a closer look at why precompiling pyc files failed. There's not enough output here to see.

[2FF0:2F08][2024-04-03T14:34:56]i301: Applying execute package: compileall_AllUsers, action: Install, path: C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe, arguments: '"C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe" -3.12 -E -s -Wi "D:\EDM115\Programmes\Python312\Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py2_|lib2to3\\tests|venv\\scripts" "D:\EDM115\Programmes\Python312\Lib"'
[2FF0:2F08][2024-04-03T14:35:05]e000: Error 0x80070001: Process returned error: 0x1
[2FF0:2F08][2024-04-03T14:35:05]e000: Error 0x80070001: Failed to execute EXE package.
[3478:09C0][2024-04-03T14:35:05]e000: Error 0x80070001: Failed to configure per-machine EXE package.
[3478:09C0][2024-04-03T14:35:05]w350: Applied non-vital package: compileall_AllUsers, encountered error: 0x80070001. Continuing...
[2FF0:2F08][2024-04-03T14:35:05]i301: Applying execute package: compileallO_AllUsers, action: Install, path: C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe, arguments: '"C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe" -3.12 -O -E -s -Wi "D:\EDM115\Programmes\Python312\Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py2_|lib2to3\\tests|venv\\scripts" "D:\EDM115\Programmes\Python312\Lib"'
[2FF0:2F08][2024-04-03T14:35:15]e000: Error 0x80070001: Process returned error: 0x1
[2FF0:2F08][2024-04-03T14:35:15]e000: Error 0x80070001: Failed to execute EXE package.
[3478:09C0][2024-04-03T14:35:15]e000: Error 0x80070001: Failed to configure per-machine EXE package.
[3478:09C0][2024-04-03T14:35:15]w350: Applied non-vital package: compileallO_AllUsers, encountered error: 0x80070001. Continuing...
[2FF0:2F08][2024-04-03T14:35:15]i301: Applying execute package: compileallOO_AllUsers, action: Install, path: C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe, arguments: '"C:\ProgramData\Package Cache\29104347204BF2D95418EA28730B788408D036EB\py.exe" -3.12 -OO -E -s -Wi "D:\EDM115\Programmes\Python312\Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py2_|lib2to3\\tests|venv\\scripts" "D:\EDM115\Programmes\Python312\Lib"'
[2FF0:2F08][2024-04-03T14:35:25]e000: Error 0x80070001: Process returned error: 0x1
[2FF0:2F08][2024-04-03T14:35:25]e000: Error 0x80070001: Failed to execute EXE package.
[3478:09C0][2024-04-03T14:35:25]e000: Error 0x80070001: Failed to configure per-machine EXE package.
[3478:09C0][2024-04-03T14:35:25]w350: Applied non-vital package: compileallOO_AllUsers, encountered error: 0x80070001. Continuing...

@zooba
Copy link
Member

zooba commented Apr 4, 2024

Actually, the heart of the matter is really in pathlib:

CAQuietExec64:    File "C:\Users\EDM115\AppData\Local\Temp\tmphbeisq9d\pip-24.0-py3-none-any.whl\pip\_internal\metadata\importlib\_envs.py", line 96, in find_linked
CAQuietExec64:      if not path.is_dir():
CAQuietExec64:             ^^^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\pathlib.py", line 875, in is_dir
CAQuietExec64:      return S_ISDIR(self.stat().st_mode)
CAQuietExec64:                     ^^^^^^^^^^^
CAQuietExec64:    File "D:\EDM115\Programmes\Python312\Lib\pathlib.py", line 840, in stat
CAQuietExec64:      return os.stat(self, follow_symlinks=follow_symlinks)
CAQuietExec64:             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CAQuietExec64:  OSError:  Le chemin d’accès ne peut pas être parcouru car il contient un point de montage non approuvé: 'C:\\Program Files\\Csound6_x64\\bin'

@barneygale We're not supposed to ever raise exceptions through is_dir calls, right? (Exception message is "The path cannot be traversed because it contains an untrusted mount point" as I mentioned in the earlier reply)

@EDM115
Copy link
Author

EDM115 commented Apr 4, 2024

It appears that Csound6_x64's installer overrides the global PYTHONPATH environment variable

It indeed does :
image
What is Csound ? I couldn't tell you. Why I have it ? idk either, but I do music production and I believe that there's one VST I installed that depends on it and installed it

@zooba
Copy link
Member

zooba commented Apr 4, 2024

I do music production as well (mostly mixing) and also coding so I'm kinda interested to figure out what it does 😆 Looks like it could be fun

But chances are you can delete the variable and the install should be fine after that. We can also make fixes upstream as well, though.

@EDM115
Copy link
Author

EDM115 commented Apr 4, 2024

also an interesting thing : the path to Csound (C:\Program Files\Csound6_x64) isn't a folder, but a symlink (of a symlink)

around a year ago I moved most stuff from my primary drive to the secondary (links to D:\EDM115\Programmes\Programs\Csound6_x64)
months later, upon a yearly pc cleanup, i moved a lot of folders to an external drive (F:\Symlinks\Programs\Csound6_x64)
mind you, the drive F wasn't plugged in when installing python, so that folder was anyway unreachable

@zooba
Copy link
Member

zooba commented Apr 4, 2024

isn't a folder, but a symlink

This will be why Windows Installer was blocked from accessing it - this is a typical pattern used by attackers to intercept legitimate installers. Probably it works okay if the path is "normal".

@Vynce
Copy link
Contributor

Vynce commented Apr 24, 2024

I just ran into this issue as well. I think there's a broader problem here. I've tested with 3.12 here, but the issue exists at least as far back as 3.8.

Minimal steps to reproduce on a fresh Windows 11 installation

Preparation

The goal here is to get pip installed in the Python 3.12 user site-packages without having Python 3.12 installed at the end of the process. These steps are a bit contrived because I couldn't figure out how to get into this state naturally, but I've seen it in the field.

  1. Install Python 3.12.3 using this installer. Just click the "Install Now" button.
  2. Install pip into user site-packages:
> py -3.12 -m pip install --ignore-installed --user pip
Collecting pip
  Downloading pip-24.0-py3-none-any.whl.metadata (3.6 kB)
Downloading pip-24.0-py3-none-any.whl (2.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 6.4 MB/s eta 0:00:00
Installing collected packages: pip
Successfully installed pip-24.0
  1. Temporarily rename the user site-packages to preserve it during uninstall. This shouldn't be necessary, but the uninstall ends up uninstalling pip from the user site-packages (instead of the system Python) due to this bug.
mv C:\Users\user\AppData\Roaming\Python\Python312 C:\Users\user\AppData\Roaming\Python\Python312bak
  1. Uninstall Python 3.12.3.
  2. Rename the user site-packages back:
mv C:\Users\user\AppData\Roaming\Python\Python312bak C:\Users\user\AppData\Roaming\Python\Python312

Reproduction

  1. Install Python 3.12.3 again using this installer. Just click the "Install Now" button.
  2. The installation logs show that pip wasn't installed as expected:
MSI (s) (B8:28) [16:18:35:436]: Executing op: CustomActionSchedule(Action=UpdatePip,ActionType=1089,Source=BinaryData,Target=CAQuietExec64,CustomActionData="C:\Users\user\AppData\Local\Programs\Python\Python312\python.exe" -E -s -m ensurepip -U --default-pip)
MSI (s) (B8:40) [16:18:35:443]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI4763.tmp, Entrypoint: CAQuietExec64
MSI (s) (B8:90) [16:18:35:443]: Generating random cookie.
MSI (s) (B8:90) [16:18:35:462]: Created Custom Action Server with PID 1584 (0x630).
MSI (s) (B8:C0) [16:18:35:479]: Running as a service.
MSI (s) (B8:C0) [16:18:35:479]: Hello, I'm your 32bit Impersonated custom action server.
CAQuietExec64:  Looking in links: c:\Users\user\AppData\Local\Temp\tmpbvvknrmu
MSI (s) (B8:28) [16:18:41:996]: Executing op: End(Checksum=0,ProgressTotalHDWord=0,ProgressTotalLDWord=311632)
CAQuietExec64:  Requirement already satisfied: pip in c:\users\user\appdata\roaming\python\python312\site-packages (24.0)
  1. Verify that pip isn't installed in the system site-packages, but is still present in the user site-packages:
> py -3.12 -E -s -m pip -h
C:\Users\user\AppData\Local\Programs\Python\Python312\python.exe: No module named pip

> ls C:\Users\user\AppData\Local\Programs\Python\Python312\Lib\site-packages
README.txt

> ls C:\Users\user\AppData\Roaming\Python\Python312\site-packages
pip
pip-24.0.dist-info
  1. Trying to install pip using the same method as the installer fails with the same message:
> C:\Users\user\AppData\Local\Programs\Python\Python312\python.exe -E -s -m ensurepip -U --default-pip
Looking in links: c:\Users\user\AppData\Local\Temp\tmpwljdworl
Requirement already satisfied: pip in c:\users\user\appdata\roaming\python\python312\site-packages (24.0)

Analysis

The -s in the ensurepip invocation tells Python to ignore the user site-packages, but ensurepip launches its own subprocess to run pip and loses the -E -s flags in the process. This was fixed from the ensurepip side in #90355, but that fix specifically propagates the -I isolated mode flag, which is not fully enabled by the -E -s flags that the installer uses.

There may be a similar issue here: https://github.com/python/cpython/blob/v3.12.3/Mac/BuildScript/scripts/postflight.ensurepip#L13

@zooba
Copy link
Member

zooba commented Apr 24, 2024

Thanks @Vynce for the analysis. This is a very different root cause from the original report on this bug, but it's certainly viable.

Given I don't think we can do anything specific about the original problem, as we don't control Windows Installer's security enforcement, I'm fine with reusing the issue number for ensurepip not propagating those two flags. Arguably, ensurepip should always run its subprocess with -E and possibly with -s as the intent is probably not to install into user-site packages.

(@pradyunsg FYI, or if you have another idea)

zooba pushed a commit that referenced this issue May 22, 2024
)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue May 22, 2024
…ythonGH-118257)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
(cherry picked from commit c9073eb)

Co-authored-by: Michael Vincent <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue May 22, 2024
…ythonGH-118257)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
(cherry picked from commit c9073eb)

Co-authored-by: Michael Vincent <[email protected]>
zooba pushed a commit that referenced this issue May 22, 2024
)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
(cherry picked from commit c9073eb)

Co-authored-by: Michael Vincent <[email protected]>
estyxx pushed a commit to estyxx/cpython that referenced this issue Jul 17, 2024
…ythonGH-118257)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
zooba pushed a commit that referenced this issue Sep 18, 2024
)

ensurepip forks a subprocess to run pip itself, but that subprocess only inherits a -I isolated mode flag (see _run_pip() in Lib/ensurepip/__init__.py), not the "-E -s" flags that the installer has been using. This means that parts of ensurepip don't actually run in an isolated environment and can make incorrect decisions based on packages installed in the user site-packages.
(cherry picked from commit c9073eb)

Co-authored-by: Michael Vincent <[email protected]>
@EDM115
Copy link
Author

EDM115 commented Oct 22, 2024

@zooba since all PRs that fixes this issue are merged, should we close this ?

@zooba
Copy link
Member

zooba commented Oct 23, 2024

I left a question about whether ensurepip should always use -E -s, but that can be answered even after the issue is closed.

@zooba zooba closed this as completed Oct 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS-windows topic-ensurepip type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants