1

This works in python shell, but not when I execute it with python -c, what is the syntax error here?

I need to update just one value in file myjson.json

python3.6 -c "import json; with open('myjson.json', 'r+') as jsonFile:  data = json.load(jsonFile); data['root']['target']['branch'][0] = 'updated_value'; jsonFile.seek(0); json.dump(data, jsonFile, indent=4); jsonFile.truncate()"
  File "<string>", line 1
    import json; with open('myjson.json', 'r+') as jsonFile:  data = json.load(jsonFile);  data['root']['target']['branch'][0] = 'updated_value'; jsonFile.seek(0); json.dump(data, jsonFile, indent=4); jsonFile.truncate()
                    ^
SyntaxError: invalid syntax
rodee
  • 3,233
  • 5
  • 34
  • 70
  • 2
    It is surely preferable from the maintainability point of view to write the program into a file and execute the file. – DYZ Sep 23 '20 at 22:06

1 Answers1

3

The syntax of Python is pretty much married to indent, and does not work well on a single line. In particular, many statements, including with and if, cannot have any other statements before them (specifically, I believe any statement that indents, i.e. that has a trailing colon). Thus, this is invalid, whether in Python shell, Python script or -c argument:

a = 1; if a == 1: print(a)

It must be written as

a = 1
if a == 1: print(a)

or

a = 1
if a == 1:
    print(a)

If you want to pass such a program from shell, you have to pass a newline into the -c parameter. For example, in bash:

python3 -c $'a = 1\nif a == 1: print(a)'

(The bash syntax $'...' quotes a string in such a way that control sequences such as \n are recognised.)

EDIT: This is the literal answer to the question. DYZ is absolutely correct in the comment that it is not a great practice trying to mash Python into a one-liner. Making a script file makes sense. If for whatever reason you can't, using a heredoc will massively improve readability:

cat << EOF | python3
a = 1
if a == 1:
    print(a)
EOF

EDIT2: There are better tools to update a value in a JSON file, if you are okay with not doing it with Python. The easiest one is jq, a tool whose whole reason of existence is manipulating JSON:

jq '.root.target.branch[0] = "updated_value"' myjson.json
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Thanks for the help @Amadan, I have another problem to solve using `jq`, if possible, can you please take a look at https://stackoverflow.com/q/64144681/2748513 thank you. – rodee Oct 01 '20 at 13:56