How to pass dictionary as command line argument to Python script? I need to get dictionary where key is string and value is list of some elements – for example to look like:
Here's another method using stdin. That's the method you want for a json cgi interface (i.e. having a web server pass the request to your script):
Python:
import json, sys
request = json.load( sys.stdin )
...
To test your script from a Linux terminal:
echo '{ "key1": "value 1", "key2": "value 2" }' | python myscript.py
To test your script from a Windows terminal:
echo { "key1": "value 1", "key2": "value 2" } | python myscript.py
I started off with @chander's excellent answer, but was running into issues with special character escaping, both at the shell/command level and within the python script. Saving the JSON
to a file and then passing that filename as a parameter to the script would be a possible solution, but in my situation that was going to be rather complicated.
So instead I decided to url encode the string at the argument level and decode it inside the Python
script. This means that whatever is calling the python script needs to url-encode the command-line argument that is the JSON
string. There are numerous online tools that let you sandbox with url-encoding a string. In my case, a nodejs
script invokes the python script call and can easily url encode the JSON
.
Inside the Python
script, it looks like this (you don't have to use argparse
, but I like it):
import json
import argparse
from urllib.parse import unquote
# Set up CLI Arguments
parser = argparse.ArgumentParser()
# Required Arguments
parser.add_argument("-c", "--config", required=True,
help="JSON configuration string for this operation")
# Grab the Arguments
args = parser.parse_args()
jsonString = unquote(args.config)
print(jsonString)
config = json.loads(jsonString)
print(config)
Follow this steps to read either JSON
or Dictionary
as Command Line Argument without even Escaping the Double or single quotes for Python:
import win32.win32api
pip install pywin32
to install this module in your machine.cmdArguments
variable:cmdArguments = win32.win32api.GetCommandLine()
JSON/Dictionary
in the last argument in the command line arguments, so suppose if you have the JSON/Dictionary
passed as last argument in command line, then the following line can fetch the JSON/Dictionary
as a separate argument and the JSON/Dictionary
will be stored in a variable named jsonstr
like this:jsonstr = ' '.join(cmdArguments.split(' ')[4:])
whitespaces
and we need to combine it to make it as a single argument.jsonstr
then you will get the same JSON/Dictionary
that was passed in the command line arguments section.import json
import win32.win32api
cmdArguments = win32.win32api.GetCommandLine()
jsonstr = ' '.join(cmdArguments.split(' ')[4:])
print(json.loads(jsonstr)) #To ensure that same JSON/Dictionary object is printed, json.loads() is used to convert JSON to DICT, you can ignore json.loads() if you want JSON object.
NameOfProgram
is the name of the python script:py <NameOfProgram.py> {"Name":"Sample Name","Salary":"20 k","Class":"First-Class"}
{'Name':'Sample Name','Salary':'20 k','Class':'First-Class'}
The important thing to note here is that at the command line you cannot pass in python objects as arguments. The current shell you are using will parse the arguments and pass them in according to it's own argument parsing rules.
That being said, you cannot pass in a python dictionary. However, things like JSON can allow you to get pretty darn close.
JSON - or JavaScript Object Representation is a way of taking Python objects and converting them into a string-like representation, suitable for passing around to multiple languages. That being said, you could pass in a string like this:
python saver.py '{"names": ["J.J.", "April"], "years": [25, 29]}'
In your python script, do this:
import json
data=json.loads(argv[1])
This will give you back a dictionary representing the data you wanted to pass in.
Likewise, you can take a python dictionary and convert it to a string:
import json
data={'names': ["J.J.", "April"], 'years': [25,29]}
data_str=json.dumps(data)
There are other methods of accomplishing this as well, though JSON is fairly universal. The key thing to note is that regardless of how you do it - you won't be passing the dictionary into Python, - you'll be passing in a set of arguments (which will all be strings) that you'll need to somehow convert into the python type you need.
@EvanZamir - note that (generally) in a shell, you need to escape quotes if they appear in your quoted string. In my example, I quote the JSON data with single quotes, and the json string itself uses double quotes, thereby obviating the need for quotes.
If you mix quotes (use double quotes to quote the argument, and double quotes inside), then the shell will require it to be escaped, otherwise the first double quote it encounters is considered the "closing quote" for the argument. Note in the example, I use single quotes to enclose the JSON string, and double quotes within the string. If I used single quotes in the string, I would need to escape them using a backslash, i.e.:
python saver.py '{"names": ["J.J.", "April\'s"], "years": [25, 29]}'
or
python saver.py "{\"names\": [\"J.J.\", \"April's\"], \"years\": [25, 29]}"
Note the quoting stuff is a function of your shell, so YMMV might vary (for example, if you use some exec method to call the script, escaping might not be required since the bash shell might not be invoked.)