Handle spaces in argparse input
Asked Answered
C

7

68

Using python and argparse, the user could input a file name with -d as the flag.

parser.add_argument("-d", "--dmp", default=None)

However, this failed when the path included spaces. E.g.

-d C:\SMTHNG\Name with spaces\MORE\file.csv

NOTE: the spaces would cause an error (flag only takes in 'C:SMTHNG\Name' as input).

error: unrecognized arguments: with spaces\MORE\file.csv

Took me longer than it should have to find the solution to this problem... (did not find a Q&A for it so I'm making my own post)

Cooe answered 10/8, 2013 at 0:9 Comment(0)
C
50

Simple solution: argparse considers a space filled string as a single argument if it is encapsulated by quotation marks.

This input worked and "solved" the problem:

-d "C:\SMTHNG\Name with spaces\MORE\file.csv"

NOTICE: argument has "" around it.

Cooe answered 10/8, 2013 at 0:9 Comment(8)
As we usually read around here... feel free to accept your answer :DUrinalysis
This isn't about argparse; this is how shells parse arguments on most systems (and how programs fake shell-style-parsing on the systems that don't have real shells). By the time you get to the argparse module, your original version is already 4 separate arguments, and argparse can't do anything about that.Lorenalorene
Quotation doesn't help in my case, I still get error: unrecognized arguments:Becky
@Shaman, just throwing a guess out there -- if you copy-pasted the arguments, they might be the wrong unicode. “ is different than ". Other than that, more input from you might help. Does a print(argv) work?Cooe
@ofer.sheffer, in my case the arguments are generated, and all things happen in linux on server side, so no copy paste.Becky
This did not work for me either. ARGS="--datasourceFile \"../datasources/CI-CD Test Cube.smodel\"" echo $ARGS then run result: --datasourceFile "../datasources/CI-CD Test Cube.smodel" error: unrecognized arguments: Test Cube.smodel"Implead
you probably forgot to pass $ARGS with quotes: yourpythonscript "$ARGS"Witkowski
Your solution is a miracle, it saved my week.Apocryphal
B
64

For those who can't parse arguments and still get "error: unrecognized arguments:" I found a workaround:

parser.add_argument('-d', '--dmp', nargs='+', ...)
opts = parser.parse_args()

and then when you want to use it just do

' '.join(opts.dmp)
Becky answered 18/11, 2014 at 9:6 Comment(5)
What if I have a string like : ma'am which has an apostrophe(') in the middle?Sticktight
So to be honest I dont even recall writing this comment. But I think this answer is better than the accepted one because it doesn't assume anything about the shell. the accepted answer isn't about argparse - its about shell. and it appears to not work for every kind of shell out there (as noted in the comments). plus, this answer outvoted the accepted one...Cristiecristin
Passing double quotes around file path with spaces threw the same error in Windows. This workaround worked like charm.Berte
If such an optional argument is specified before the positional arguments on the command line (which is a POSIX guideline) then the optional argument will consume all the positional arguments immediately following it.Marika
This is just a workaround, not a definitive answer, for example if the string contains multiple consecutive characters (e.g. ex ample), this method will not work.Miscalculate
C
50

Simple solution: argparse considers a space filled string as a single argument if it is encapsulated by quotation marks.

This input worked and "solved" the problem:

-d "C:\SMTHNG\Name with spaces\MORE\file.csv"

NOTICE: argument has "" around it.

Cooe answered 10/8, 2013 at 0:9 Comment(8)
As we usually read around here... feel free to accept your answer :DUrinalysis
This isn't about argparse; this is how shells parse arguments on most systems (and how programs fake shell-style-parsing on the systems that don't have real shells). By the time you get to the argparse module, your original version is already 4 separate arguments, and argparse can't do anything about that.Lorenalorene
Quotation doesn't help in my case, I still get error: unrecognized arguments:Becky
@Shaman, just throwing a guess out there -- if you copy-pasted the arguments, they might be the wrong unicode. “ is different than ". Other than that, more input from you might help. Does a print(argv) work?Cooe
@ofer.sheffer, in my case the arguments are generated, and all things happen in linux on server side, so no copy paste.Becky
This did not work for me either. ARGS="--datasourceFile \"../datasources/CI-CD Test Cube.smodel\"" echo $ARGS then run result: --datasourceFile "../datasources/CI-CD Test Cube.smodel" error: unrecognized arguments: Test Cube.smodel"Implead
you probably forgot to pass $ARGS with quotes: yourpythonscript "$ARGS"Witkowski
Your solution is a miracle, it saved my week.Apocryphal
E
12

Bumped into this problem today too.

-d "foo bar"

didn't help. I had to add the equal sign

-d="foo bar"

and then it did work.

Expedition answered 2/4, 2016 at 17:7 Comment(2)
python 3.5.1 on RHEL6Expedition
This did not work for me either. my param looks like: ARGS="--datasourceFile=\"../datasources/CI-CD Test Cube.smodel\"" which echod looks like: --datasourceFile="../datasources/CI-CD Test Cube.smodel" and I get error: unrecognized arguments: Test Cube.smodel"Implead
S
3

After some experiments (python 2.7 Win10) I found out that the golden rule is to put quotes ("") around arguments which contain spaces and do NOT put if there are no spaces in argument. Even if you are passing a string/path. Also putting a single quotes ('') is a bad idea, at least for Windows.

Small example: python script.py --path ....\Some_Folder\ --string "Here goes a string"

Spence answered 1/2, 2018 at 16:18 Comment(0)
W
1

A common mistake, when forwarding bash script arguments, is to forget double quotes. for example writting this:

ARGS="C:\SMTHNG\Name with spaces\MORE\file.csv"
mypythonscript  -d $ARGS

while it should be

ARGS="C:\SMTHNG\Name with spaces\MORE\file.csv"
mypythonscript -d "$ARGS"
Witkowski answered 1/2, 2022 at 10:23 Comment(0)
F
1

There are 2 important points here (from my perspective):

  1. You do not want to replace all the spaces in the argument input.
  2. You want to use argparse interface.

My best aproax would be to use an argparse.Action with the function strip for the string:

import argparse

class StripArgument(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values.strip())

parser = argparse.ArgumentParser(
    prog=f"your program", description=__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="See '<command> --help' to read about a specific sub-command.")
parser.add_argument(
    "-n", "--variable-name", type=str, default='vx', action=StripArgument,
    help="Variable name inside something (default: %(default)s)")
Fluorene answered 17/2, 2022 at 10:5 Comment(0)
C
-4

You need to surround your path with quotes such as:

python programname.py -path "c:\My path with spaces"

In the argument parse you get a list with one element. You then have to read it like:

path = args.path[0]
Crepitate answered 21/12, 2020 at 8:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.