9

According to the official documentation "Python debugging in VS Code", launch.json can be configured to run with specific command line arguments, or you can use ${command:pickArgs} to input arguments at run time.

Examples of putting arguments in launch.json:

However, I would rather use but I would rather use ${command:pickArgs} because it makes it easier to test multiple times with different values.

The first time I tried this, I allowed VS Code to create launch.json. By default it contained the following:

            "args": [
                "${command:pickArgs}"
            ]

When I run the file, I get a dialog for inputting arguments:

Python Debugger: Current File with Arguments

However, if I put in multiple arguments, they get wrapped in quotes and treated as a single string argument. In a case where, e.g. the arguments are supposed to be numeric, an error is generated. For example, if I pass in 4 7, which both need to be cast to int, sys.argv[1] gets the value '4 7' rather than '4', yielding the error

invalid literal for int() with base 10: '4 7'

I have tried comma-separating the arguments, and putting quotes around them, and what I get is sys.argv[1] with values like '4, 7' or '"4", "7"'. Needless to say, these don't work either.

I've seen examples online of a launch.json configuration as follows:

            "args": "${command:pickArgs}"

That is, there are no brackets around ${command:pickArgs}. However, this generates a problem in that if there are spaces in the path to the Python interpreter, the path gets broken apart at the spaces. See, for example:

Spaces in python interpreter path or program result in incorrectly quoted debugging commands with arguments #233

The solution seems to be to put the brackets in, which is what I started with in the first place. Since that's what VS Code did automatically, I'm not sure where the varying examples are coming from (with or without brackets) and can't find documentation on this other than the very short mention of ${command:pickArgs} in the official documentation I linked at the very beginning.

So, I have not been able to figure out a way to pass in multiple arguments using ${command:pickArgs} (as opposed to hard-coding directly in launch.json), and the only promising solution (remove the brackets) is poorly documented, generates other errors, and the solution seems to be to put the brackets back in.

Is this possible to do at all?

3
  • Is your OS Windows? Commented Aug 23, 2024 at 21:45
  • Yes, but is that relevant? The VS Code documentation that discusses this mentions nothing about different OSes, and a simple OS-agnostic script would be called the same on Mac/Windows/Linux, e.g. python script.py arg1 arg2. Commented Aug 24, 2024 at 0:04
  • It's relevant given the prevalence of unsafe paths in Windows more than in e.g. Linux. Because as yourself pointed out, removing those square brackets solves the problem but not for all cases. Commented Aug 24, 2024 at 3:04

2 Answers 2

8

Answering my own question after further testing. I will leave it unaccepted for a while to see if other answers come in.

TL;DR

This is possible as long as there are no spaces in the path to the Python interpreter. The fact that it breaks if there are spaces in the path is a currently open bug. The question arises because of a previously attempted bug fix.

Workaround

  1. Make sure your launch.json does not have brackets around ${command:pickArgs}.
  2. Make sure the path to Python interpreter has no spaces. If it does, create a link to the environment containing the interpreter (the target) from a path that does not have spaces. On Windows in PowerShell, this looks like:
New-Item -ItemType Junction -Path C:any\path\without\spaces -Target 'C:\path to Python\environment which may\have spaces in it'

Note that the ItemType has to be Junction, not SymbolicLink. If you use a SymbolicLink, the path will be followed (it will find the interpreter) but then replaced with the target path, and the embedded spaces will still create problems.

Long-Term

Wait for currently open issue Spaces in python interpreter path or program result in incorrectly quoted debugging commands with arguments #233 to be fixed.

Explanation

As far as I can tell, this is what happened.

In a previous version of VS Code, launch.json would be created with the following configuration:

            "args": "${command:pickArgs}"

Notice there are no brackets around ${command:pickArgs}.

This works and allows the user to submit multiple command line arguments via dialog box when debugging.

However, due to a bug, there was an error if the path to the Python interpreter had spaces in it: Spaces in python interpreter path or program result in incorrectly quoted debugging commands with arguments #233.

An attempted fix inserted brackets into launch.json: Fix error in args with default config #385. This fixed the problem with spaces in the Python path, but created the problem that the question asks about, that multiple command line arguments are treated as part of the same string. This fix appears to have made it into v1.92.2, the version I am using, breaking the ability to parse command line arguments.

The solution therefore is to remove the brackets around ${command:pickArgs} introduced by the fix in issue #385, but since the Python environment I was testing had spaces in the path, this triggered issue #233.

After additional information, issue #233 was reopened. The workaround is to make sure to use an environment without spaces in the path. The long-term solution is to wait for the fix to issue #233.

Sign up to request clarification or add additional context in comments.

Comments

1

I have been fighting this for a while. I finally got fed up and remembered I'm using python so why fight vscode when it can be easily fixed in python:

launch.json

"configurations": [
  {
    "name": "Run ...",
    "type": "debugpy",
    "request": "launch",
    "program": "${workspaceFolder}/program.py",
    "console": "integratedTerminal",
    "env": { "USED_VSCODE_COMMAND_PICKARGS": "1" },
    "args": ["${command:pickArgs}"]
  }
]

program.py

import argparse, os, shlex, sys
...
argv = (
    # VSCode's ${command:pickArgs} is passed as one string, split it up
    shlex.split(" ".join(sys.argv[1:]))
    if "USED_VSCODE_COMMAND_PICKARGS" in os.environ
    else sys.argv[1:]
)
args = parser(argv)

Note: the args: [...] in launch.json can have whatever args you would normally put there including more ${command:pickArgs} and/or ${input:*} args

example

  1. VSCode > Run and Debug > Run ...
  2. In the "Command Line Arguments" popup enter:
    are these "the args" --you -R 'looking for' -?
  3. In program.py, argv becomes:
    ['are', 'these', 'the args', '--you', '-R', 'looking for', '-?']
    and is handled perfectly fine by the argparse parser

1 Comment

Nice workaround! They really should just add some syntax for multiple arguments like 'arg1' && 'arg2' ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.