Search code examples
pythonpowershellargparse

Python argparse not working corrrectly with path in Windows


The argparse library in python doesn't work for any path containing a space and \ (backslash) at the end. The parser will parse the backslash at the end of path to be " (double quotation).

The code below is a sample that has same problem:

import argparse


if __name__=="__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-w', '--weight', type=str)

    args = parser.parse_args()

    print(args.weight_path)

For example in PowerShell:

PS > python sample.py -w ".\test test\"
.\test test"

It does work for any path which doesn't contain a space:

PS > python sample.py -w ".\testtest\"
.\test test\
PS > python sample.py -w "testtest\"
test test\
PS > python sample.py -w "testtest"
test test

Is there any issues with using argparse with PowerShell?

I don't even know how to search for a solution to this problem...


Solution

  • You're seeing what is a bug in Windows PowerShell, which has since been corrected in PowerShell (Core) 7+:

    • To PowerShell, based on the syntax of its own string literals, the verbatim value of string ".\test test\" is .\test test\, because \ has no special meaning in PowerShell (PowerShell's escape character is `, the so-called backtick).

    • However, based on the most widely used conventions for parsing a process command line on Windows, this string must be placed as ".\test test\\" on the process command line constructed behind the scenes when calling an external program, given that processes are expected to parse \" as an escaped " char.

      • While PowerShell (Core) 7+ now does do that behind the scenes, Windows PowerShell does not: it places ".\test test\", which causes Python to interpret the closing \" as a verbatim " (while not complaining that a closing unescaped " - i.e. one with syntactic function - is then missing).

    The workaround for Windows PowerShell is to manually double the \ char. before the closing ":

    # Windows PowerShell only: double the \ before the closing "
    python sample.py -w ".\test test\\"
    

    As an aside: While PowerShell (Core) 7+ has fixed this particular problem, there is still a long-standing problem with respect to intentionally embedded " characters in arguments passed to external programs - see this answer.