Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Argparse: Raw string input

Apologies if this has been asked before, I did search for it but all hits seemed to be about python raw strings in general rather than regarding argparse.

Anyways, I have a code where the user feeds in a string and then this string is processed. However, I have a problem as I want my code to be able to differentiate between \n and \\n so that the user can control if they get a line break or \n appear in the output (respectively).

This in itself is quite simple, and I can get the logic working to check the string, etc. However, argparse doesn't seem to keep the input string raw. So if I were to write: Here is a list:\nItem 1 it gets parsed as Here is a list:\\nItem 1. As the exact same thing gets parsed if I were to replace \n with \\n in the input string, it becomes impossible to differentiate between the two.

I could include a bodge (for example, I could make the user enter say $\n for \n to appear in the output, or just \n for a line break). But this is messy and complicates the usage of the code.

Is there a way to ensure the string being parsed by argparse is raw? (I.e. if I enter \n it parses \n and not \\n)

Again, sorry if this has been asked before, but I couldn't find an answer and after over an hour of trying to find an answer, I'm out of ideas (bar the bodge). Cheers in advance for any and all help.

Example code (sorry if this doesn't work, not sure how best to do example code for argparse!):

import argparse

parser = argparse.ArgumentParser( description = 'Test.' )
parser.add_argument( 'text', action = 'store', type = str, help = 'The text to parse.' )

args = parser.parse_args( )

print( repr( args.text ) )
like image 231
Steve Avatar asked Aug 24 '16 10:08

Steve


2 Answers

Here's a possible solution to your problem:

import argparse

parser = argparse.ArgumentParser(description='Test.')
parser.add_argument('text', action='store', type=str, help='The text to parse.')

args = parser.parse_args()

print '-' * 80
raw_text = eval('"' + args.text.replace('"', '\\"') + '"')
print raw_text
print '-' * 80
print args.text

But be aware of one thing, eval really is dangerous

like image 81
BPL Avatar answered Oct 17 '22 22:10

BPL


As noted in the comments, argparse works with sys.argv, a list which is produced by the shell and Python interpreter.

With a simple argv echo script:

0928:~/mypy$ cat echo_argv.py
import sys
print(sys.argv)

I get (with a bash shell):

0929:~/mypy$ python echo_argv.py Here is a list:\nItem 1 
['echo_argv.py', 'Here', 'is', 'a', 'list:nItem', '1']
0931:~/mypy$ python echo_argv.py "Here is a list:\nItem 1 "
['echo_argv.py', 'Here is a list:\\nItem 1 ']
0931:~/mypy$ python echo_argv.py "Here is a list:\\nItem 1 "
['echo_argv.py', 'Here is a list:\\nItem 1 ']

argparse treats that argv as a list of strings. It does nothing to those strings, at least not with the default None type parameter.

like image 32
hpaulj Avatar answered Oct 17 '22 22:10

hpaulj