microsoft / vscode-python

Python extension for Visual Studio Code
https://aka.ms/pvsc-marketplace
MIT License
4.29k stars 1.17k forks source link

Check on debug launch configuration's `python` field prevents container debugging #22884

Open bwateratmsft opened 7 months ago

bwateratmsft commented 7 months ago

The Docker extension resolves a Python debug configuration in order to support Python debugging. Included in that resolved debug configuration is the python field, with a value of just python3. This is because this is the command to use for launching Python in the container. However, validation of that field is done against the host, so if the host and container don't both have python3, debugging fails. We've tried changing it to python, which worked on Windows, but failed on Mac and Linux.

Is there a way to override this check to stop it from validating against the host when it should not be?

An additional strange thing we've noticed is that the error seems to only show up on Insiders. The code doesn't seem to be Insiders only so it's confusing why it would be doing this.

bwateratmsft commented 7 months ago

Downstream Docker extension bug: https://github.com/microsoft/vscode-docker/issues/4209

karrtikr commented 7 months ago

Can you provide us the full launch.json config for python that you're using? And in the case that it fails, please provide the logs:

Output for Python in the Output panel (ViewOutput, change the drop-down the upper-right of the Output panel to Python)

``` XXX ```

karrtikr commented 7 months ago

Just to clarify, Python extension is running on the host, where "python" or "python3" does not exist, leading to the issue?

bwateratmsft commented 7 months ago

Here's the intermediate launch.json configuration--this is what the Docker extension takes as input and turns into a Python launch configuration. This is for a simple FastAPI project.

{
    "name": "Docker: Python - Fastapi",
    "type": "docker",
    "request": "launch",
    "preLaunchTask": "docker-run: debug",
    "python": {
        "pathMappings": [
            {
                "localRoot": "${workspaceFolder}",
                "remoteRoot": "/app"
            }
        ],
        "projectType": "fastapi"
    },
}

Here's the fully resolved debug configuration given to the Python extension's debug resolver:

{
    "name": "Docker: Python - Fastapi",
    "type": "python",
    "request": "launch",
    "preLaunchTask": "docker-run: debug",
    "python": "python3", // This is what is getting validated against the host improperly
    "__configurationTarget": 6,
    "pathMappings": [
        {
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "/app"
        }
    ],
    "justMyCode": true,
    "django": false,
    "fastapi": true,
    "jinja": false,
    "dockerOptions": {
        "containerName": "fastapi-dev",
        "dockerServerReadyAction": {
            "containerName": "fastapi-dev",
            "pattern": "Uvicorn running on (https?://\\S+|[0-9]+)",
            "uriFormat": "%s://localhost:%s"
        }
    },
    "debugLauncherPath": "d:\\vscode-docker\\resources\\python\\launcher.py",
    "debugAdapterHost": "localhost",
    "console": "integratedTerminal",
    "internalConsoleOptions": "openOnSessionStart",
    "module": "uvicorn",
    "redirectOutput": true,
    "args": [
        "main:app",
        "--host",
        "0.0.0.0",
        "--port",
        "8000",
        "docker",
        "fastapi-dev"
    ],
    "cwd": ".",
    "debugAdapterPython": "${command:python.interpreterPath}",
    "debugLauncherPython": "${command:python.interpreterPath}"
}

This debug configuration will launch debugging against a container that is idling.

Just to clarify, Python extension is running on the host, where "python" or "python3" does not exist, leading to the issue?

Yes, the Python extension is running on the host, a Windows machine. Running python opens the Python 3 interpreter, but running python3 opens a Windows Store page to install Python as an app. As far as I know, this is a new behavior on Windows and I think it is why this problem only appeared now.

bwateratmsft commented 7 months ago

Here is the output from the Python output log with log level set to trace:

2024-02-07 09:32:41.405 [debug] Found cached env for C:\Python312\python.exe
2024-02-07 09:32:43.072 [debug] No cached env found for python3
2024-02-07 09:32:43.073 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\bw\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\bw\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-07 09:32:43.075 [debug] Failed to get file info for python3 [Error: ENOENT: no such file or directory, lstat 'C:\Users\bw\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\bw\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-07 09:32:43.076 [debug] Environment resolver resolved python3 for {"name":"","location":"","kind":"unknown","executable":{"filename":"python3","sysPrefix":"","ctime":-1,"mtime":-1},"display":"Python","version":{"major":-1,"minor":-1,"micro":-1,"release":{"level":"final","serial":-1}},"arch":1,"distro":{"org":""},"source":[],"id":"PYTHON3","detailedDisplayName":"Python"} to undefined
2024-02-07 09:32:43.076 [debug] Resolved python3 using downstream locator
2024-02-07 09:32:43.076 [debug] Found cached env for C:\Python312\python.exe
2024-02-07 09:32:43.086 [debug] Activation Commands received undefined for shell cmd, resource d:\Sandbox\FastAPI and interpreter C:\Python312\python.exe
2024-02-07 09:32:43.090 [debug] No cached env found for python3
2024-02-07 09:32:43.091 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\bw\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\bw\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-07 09:32:43.094 [debug] Failed to get file info for python3 [Error: ENOENT: no such file or directory, lstat 'C:\Users\bw\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\bw\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-07 09:32:43.095 [debug] Environment resolver resolved python3 for {"name":"","location":"","kind":"unknown","executable":{"filename":"python3","sysPrefix":"","ctime":-1,"mtime":-1},"display":"Python","version":{"major":-1,"minor":-1,"micro":-1,"release":{"level":"final","serial":-1}},"arch":1,"distro":{"org":""},"source":[],"id":"PYTHON3","detailedDisplayName":"Python"} to undefined
2024-02-07 09:32:43.095 [debug] Resolved python3 using downstream locator
2024-02-07 09:32:43.097 [error] Invalid Python Path 'python3'
2024-02-07 09:32:44.815 [debug] Clearing context for python dependencies not installed: ms-python.python.Python
2024-02-07 09:32:44.816 [debug] Found cached env for C:\Python312\python.exe
karrtikr commented 7 months ago

Thanks for that.

We do the validation yes, but I think this question is better suited for debugpy. We assume that the "python" specified contains a valid python binary in the host, but seems like that depends on the way launch config is specified?

If so, is there a way we can detect that, and thereby not do host validation in that case?

bwateratmsft commented 7 months ago

It seems like it has started occurring in non-Insiders builds as well now.

bwateratmsft commented 7 months ago

Thanks for that.

We do the validation yes, but I think this question is better suited for debugpy. We assume that the "python" specified contains a valid python binary in the host, but seems like that depends on the way launch config is specified?

If so, is there a way we can detect that, and thereby not do host validation in that case?

Perhaps if a custom debugLauncherPath is specified, the check should be skipped? Or a new flag could be added to override the check?

karrtikr commented 7 months ago

I think that could work, we should probably avoid adding a new flag though, unless absolutely needed.

bwateratmsft commented 7 months ago

What's confusing to me is that this is just now appearing, when a few days ago it was only showing up in Insiders, and before that not at all. It seems like this should have come up years ago.

int19h commented 7 months ago

debugpy itself doesn't do any validation in this case, it just uses the provided "python" etc values as is when building the command line. The validation code probably lives in https://github.com/microsoft/vscode-python-debugger?

bwateratmsft commented 7 months ago

We're not yet using the Python Debugger extension, blocked by https://github.com/microsoft/vscode-python-debugger/issues/194. We're still using the regular Python extension, so the validation is happening there.

karrtikr commented 7 months ago

@int19h Python extension does the validation, yes, but we do the validation assuming that "python" carries a valid executable in the host, which is not the case here as it refers to the "python" in the container instead.

What I wanted to check with debugpy is if there is a flag, like debugLauncherPath that we can check to approximately tell us that this "python" does not have be in the host, in which case we'll skip validation.

TrunovK commented 7 months ago

I have the same exeption and I try'd many ways to fix this problem.

2024-02-08 14:06:06.128 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.140 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.144 [error] Invalid Python Path 'python3'

The last one is: I install Python 3.12 for all users and copy folder C:\Program Files\Python312 to C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3 and finally debuging start to work!

int19h commented 7 months ago

@karrtikr debugpy doesn't have any knowledge of that either. "debugLauncherPath" just tells it to use a custom launcher script, but that can be done for various reasons; using a wrapper script to effectively "remote" the launch, like Docker does, is only one possibility. I think that if some way to signal this is desirable, the extension should just introduce its own flag on debug config (which debugpy will simply ignore, as any other unknown property), and require clients that want to skip verification to set this flag also.

However, I'm not sure that verification is a good idea here in the first place. Generally speaking, specifying "python" explicitly is already an advanced scenario (since the usual flow is to just select the appropriate interpreter from the status bar). Also, given that the launch command usually executes in a shell, even locally there's a legitimate case when "python" wouldn't be a valid executable binary: it can also be a shell alias. So e.g. this is valid:

"python": "exec"
"pythonArgs": ["custom-python-wrapper.sh"]

but I don't know how this can even be validated without actually running it in the user's choice of shell.

By the way, what does the validator do when "python" is an array value? e.g. the above can also be written thus:

"python": ["exec", "custom-python-wrapper.sh"]
karrtikr commented 7 months ago

Also, given that the launch command usually executes in a shell, even locally there's a legitimate case when "python" wouldn't be a valid executable binary: it can also be a shell alias. So e.g. this is valid:

Right. We run the interpreter specified as part of validation, so this scenario is covered.

By the way, what does the validator do when "python" is an array value? e.g. the above can also be written thus:

package.json contribution currently states that this value can only be a string, so we need not to do this yet.

karrtikr commented 7 months ago

@bwateratmsft How critical of an issue this is? It'll help with prioritizing it. The proposed solutions are:

My preference would be to go route 1, as to avoid adding such a flag prematurely.

bwateratmsft commented 7 months ago

@karrtikr this blocks in-container debugging entirely unless the user has python3 available on the PATH environment variable. We can advise them to install python3 either from the website or the Windows Store app--either would work--so there is a reasonable workaround. My Linux VM and Macbook both had python3 already.

I still don't understand why this is only appearing now, it seems like it should have appeared years ago. The only thing I can think of is a Windows update changing the dynamic somehow.

int19h commented 7 months ago

Win10 used to ship with stubs for python.exe and python3.exe that would direct the user to app store page for Python when launched, so a simple check to see if the binary is present would succeed thanks to those. I wonder if they have been removed in Win11 recently.

bwateratmsft commented 7 months ago

They're still present in Win11 at least on my machine, and running them leads to a Windows Store page. So a check for the exe's existence would succeed, but something like python3 --version would not.

leepillen commented 6 months ago

I have the same exeption and I try'd many ways to fix this problem.

2024-02-08 14:06:06.128 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.140 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.144 [error] Invalid Python Path 'python3'

The last one is: I install Python 3.12 for all users and copy folder C:\Program Files\Python312 to C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3 and finally debuging start to work!

I'm having exactly the same problem. I tried this as a last resort (copied the files from my Conda environment into C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3). My program ran - but none my breakpoints were being hit.

AlexDorobantiu commented 6 months ago

I had the same problem on Windows and copied the entire Python 3.11 from the install folder into C:\Users\<YourUser>\AppData\Local\Programs\Microsoft VS Code and then duplicated python.exe and renamed it to python3.exe. Debugging passed to the next problem, which was related to the fact that the current working directory is not where it should be when you start the task, so I had to improve some paths in the tasks.json file, but it got working with debugging breakpoints and reloading.

Retrospected commented 6 months ago

I was having the same issue. Current easy workaround for those who are looking for one: make sure python3 is found in your PATH. I copied python.exe to python3.exe in my installation dir (%LOCALAPPDATA%\Programs\Python\Python311) for the time being. Test whether python3 starts python from the commandline and not the Microsoft Store, if it does you should be good to go.

2Dews commented 5 months ago

I tried the workarounds mentioned above but was not able to hit breakpoints in containers. Are there any other work arounds? I tried pre-release and insiders and both still have the problem. I set up a mklink so that python3 --version returns the correct response from CMD but VS Code still doesn't think it's an exe.

JanKowalik commented 5 months ago

Is there any ETA for fixing this issue? Can someone point out the recommended workaround, please?

JanKowalik commented 5 months ago

@Retrospected Thanks, that workaround does it for me

daveisagit commented 4 months ago

Did this start happening in a particular version, i.e. is there a version where this works? I spent a long time on many very simple intros to _VS Code Debug with Docker Tutorial_s. Failing many times after re-installs and using different machines before finding this thread. 😞

daveisagit commented 4 months ago

I have the same exeption and I try'd many ways to fix this problem.

2024-02-08 14:06:06.128 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.140 [warning] Failed to check if python3 is an executable [Error: ENOENT: no such file or directory, lstat 'C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'lstat',
  path: 'C:\\Users\\user\\AppData\\Local\\Programs\\Microsoft VS Code\\python3'
}
2024-02-08 14:06:06.144 [error] Invalid Python Path 'python3'

The last one is: I install Python 3.12 for all users and copy folder C:\Program Files\Python312 to C:\Users\user\AppData\Local\Programs\Microsoft VS Code\python3 and finally debuging start to work!

Out of all the suggested workarounds on this thread, this was the only one to work for me. 🙇