How to pass dictionary as command line argument to Python script?

PythonPython 2.7Command Line

Python Problem Overview


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:

command_line_arguments = {"names" : ["J.J.", "April"], "years" : [25, 29]}

I have tried like

if __name__ == '__main__':
    args = dict([arg.split('=') for arg in sys.argv[2:]]) # also tried with 1 but doesn't work
    main(args)

and I am calling script like

$ python saver.py names=["J.J.", "April"] years=[25, 29]

but it doesn't work, dictionary has length 0 and need 2. Can anyone help me to pass and create dictionary in main.

Python Solutions


Solution 1 - Python

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.)

Solution 2 - Python

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

Solution 3 - Python

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)

Solution 4 - Python

Even though my answer is way late. I find most of the answers here have some kind of loop hole or are unecessarily tedious. I too was in need of passing a dictionary string as a command line argument. So here you go the simplest and most sure way is as below. It works on both linux and windows Type below in a python file called somepyfile.py

import sys
i = sys.argv[1]
a = eval(i)
print(a)
print(type(a))

and now in a terminal do as below

python somepyfile.py {'hello':4}

Simple right!

Solution 5 - Python

Follow this steps to read either JSON or Dictionary as Command Line Argument without even Escaping the Double or single quotes for Python:

  1. Import the Windows32 API module for python like this:
    import win32.win32api

    If you don't have the module installed, then type: pip install pywin32 to install this module in your machine.

  2. Reading the command line arguments will be done by this line, the value of the command line arguments will be stored as a string in cmdArguments variable:

    cmdArguments = win32.win32api.GetCommandLine()

  3. It is always a good practise to pass the 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:])

    Technically, the object gets split into separate arguments due to whitespaces and we need to combine it to make it as a single argument.

  4. Now, if you print the value of jsonstr then you will get the same JSON/Dictionary that was passed in the command line arguments section.

    The complete example Code for this is:

    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.
    
  5. The example command line arguments would be like this, where NameOfProgram is the name of the python script:

    py <NameOfProgram.py> {"Name":"Sample Name","Salary":"20 k","Class":"First-Class"}

    Now output will be:

    {'Name':'Sample Name','Salary':'20 k','Class':'First-Class'}

Solution 6 - Python

Pass the command line argument as below(mind the single and double inverted commas):

"{'k1':'v1','k2':['v1','v2',1,2,3]}"

and then in your python code use eval() or ast.literal_eval()

import ast
if __name__=="__main__":
     cmd_arg=sys.argv[1]
     print(ast.literal_eval(cmd_arg))
     print(type(ast.literal_eval(cmd_arg)))

 

Solution 7 - Python

This should work:

script = ["python2.7", os.path.join(os.path.dirname(__file__), "xs_helper.py"), '\'%s\'' % json.dumps(dicData)]

Solution 8 - Python

I had the same problem and what worked for me is just use of backslash e.g.:

"{\"key\": \"value\", \"key2\": [{\"key3\":\"value\"}, ... ]}"

P.S. Tested in Windows Terminal (CMD) and also Bash (Git Bash)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPaolaJ.View Question on Stackoverflow
Solution 1 - PythonchanderView Answer on Stackoverflow
Solution 2 - PythonBuvinJView Answer on Stackoverflow
Solution 3 - PythonKohanzView Answer on Stackoverflow
Solution 4 - PythonBishamon TenView Answer on Stackoverflow
Solution 5 - PythonPrasad NadigerView Answer on Stackoverflow
Solution 6 - PythonTomato MasterView Answer on Stackoverflow
Solution 7 - PythonDeng DaochengView Answer on Stackoverflow
Solution 8 - PythonDanielView Answer on Stackoverflow