Think I found a bug in Windows installer

Hello,

I ran across a frustrating problem in the Python installer for Windows.

I have been using Python 2.7 on a Windows 10 (x64) PC to run scripts for some applications, but those scripts were updated and now called for Python 3. So, earlier today, I installed Python 3.9.2 (64-bit installer) from the Downloads page, keeping Python 2.7 just in case. Suddenly, all of my scripts were failing to run. I was getting bizarre errors like

"Error: "C:\Windows\system32\L": no such file or folder" 

in the application’s log.

I checked everything I could think of. The paths for Python 3.9 and Python 2.7 were set correctly in my system environment variables (with Python 3.9’s first). I made sure Pywin32 was installed (newest version from its website). I changed settings within the app that was trying to call the scripts. All to no avail.

Finally, after much Googling and poking around, I stumbled across the cause.

When I installed Python 3.9.2, I had selected the option “Install for all users”. This created a set of keys in the Windows Registry for file associations, which would execute “C:\Windows\py.exe” for the various Python file types (.py, .pyc, etc.). But, the command it was using to actually execute Python was put in as:

"C:\Windows\py.exe" "%L" %*

when it SHOULD have been

"C:\Windows\py.exe" "%1" %*

Note, the “L” when it should have been “1”. “%1” is the standard Windows method of specifying the first argument in the command line.

So, instead of passing the argument (e.g. the name of the script) to Python, Windows was instead expanding “%L” into “C:\Windows\system32\L” and passing that to Python, causing every script called by my application to fail! (Why does it use “C:\Windows\system32” as the folder name? Who knows…)

All of this means that the Python installer set up the file associations wrong when writing to the Windows Registry. Whomever created the installer made a typo and wrote “%L” instead of “%1”.

In order to fix the problem, I had to open Regedit.exe, go to “HKEY_CLASSES_ROOT\Python.File\shell\open\command” and edit the “(Default)” value, replacing “%L” with “%1”. I also had to do the same with the other Python-related keys (Python.ArchiveFile, Python.CompiledFile, etc.) which had a “shell\open\command” subkey anywhere in their tree.

After that, the scripts started running as expected.

Mind you, I think this may only happen specifically when the “Install for all users” option is selected in the installer. But I don’t know for sure, and I’m not about to test the alternative at this point!

aimhere

The “packaging” category is for packaging things written in Python, not the Python software itself. You may reach more relevant people posting to bugs.python.org instead.

There is nothing wrong with using “%L” compared to “%1” as the template parameter for the target file. It’s nearly the same, except it tells the shell to use the [L]ong filename, which really hasn’t been needed since the Windows 9x era. I doubt that was the problem. Using “%L” works fine on thousands of installations and all Windows versions. What happened for you is probably the case of changing one or more settings leading to something getting reset that was previously in a bad state. I’m pretty sure it will continue to work if you change the template command back to using “%L”.

I had to open Regedit.exe, go to “HKEY_CLASSES_ROOT\Python.File\shell\open\command”

You’ll be better off in the future editing the real software classes hives in “[HKLM|HKCU]\Software\Classes”. “HKCR” is a merged view that’s really only intended for reading settings, at least since Windows 2000 (NT 5.0). The merged view prefers the user hive, and falls back on the machine hive. So the key that you end up editing could be in either the machine or user hive, depending on which exists. Generally it’s important to know exactly whether you’re setting a value for the machine or just the current user, and if you don’t know which you want, you probably shouldn’t be changing anything at all. Editing HKCR directly is a practice that persists from the 1990s, from before HKCR was a merged view.

I suspect there are is some critical information missing from the original post, probably to do with how the script is being launched.

Double-clicking is the usual way to launch a Python script relying on those commands, but Explorer (and ShellExecute) definitely know how to substitute the parameter properly. So which application is reading the registry to determine how to launch the file, but failing to substitute the parameters correctly?

I didn’t address that the application might be manually expanding the progid. If it’s doing it wrong, that’s a bug in the application. What I usually assume at the outset is that people make a lot of random changes to fix a problem, often trying anything in desperation, and then misinterpret exactly what fixed it. So I simply asked to try switching back to “%L”. If it’s still broken after switching back to “%L”, then it’s outside of my scope. I would prefer that the installer used “%1” instead of “%L” in the template command, but using “%L” is not incorrect.