Transform JSON String to Dictionary using shell without escape - python

I am calling a python script from the shell, with one input argument.
python main.py """{"key1":"value1", "key2":"value2"}"""
All keys and values are strings. Once in python, I would like to convert the JSON string to a dictionary, so I have acess to the values by using the keys.
I tried the following
import json
import sys
dict_in = json.loads(sys.argv[1])
But dict_in would end up a string like that {key1:value1, key2:value2}
So it seems like I need to find a way to pass the string with quotation marks from the shell to python. I can not use escape characters since the string is provided by a different program.
Is there an elegant way to solve this?

I've found a python 2 module which can handle such cases.
Suppose you have this string:
>>> str = '{foo: bar, id: 23}'
Then you can use yaml as follows:
>>> import yaml
>>> dict = yaml.load(str)
>>> dict
{'foo': 'bar', 'id': 23}
>>> dict['foo']
'bar'
Now you have what you needed.
More info (and also python 3 support and etc.) can be found here: https://pyyaml.org/wiki/PyYAMLDocumentation

Not sure if what you passing in is important but you can pass following and get desired output:
"{\"key1\":\"value1\", \"key2\":\"value2\"}"
or
'{"key1":"value1", "key2":"value2"}'
Here is the code and output:
$cat json_convert.py
import json
import sys
dict_in = json.loads(sys.argv[1])
print (dict_in)
$ python json_convert.py '{"key1":"value1", "key2":"value2"}'
{'key1': 'value1', 'key2': 'value2'}
Also what you are passing """{"key1":"value1", "key2":"value2"}""" translates to "" + "{" + key1 + ":" + value1 + ", " + + key2 + ":" + value2 + "}" + "" if you are asking bash, if you were calling the function with that as a argument from the python itself you would get the desired results.
So really goes down to what you are calling it from.
If you still like quotes go ahead and pass """{"'"key1"'":"'"value1"'", "'"key2"'":"'"value2"'"}""" to get desired result :)

use either:
$ your_other_program | python main.py
to send the output of the other program to python, or use base64.b64encode(json.dumps(blah)) and you'll get pretty code like
'eyJtQXV0b21hdGljVGVzdExpc3QiOiBbeyJtWSI6IDguMTE0MTA1LCAibU5hbWUiOiAiYWNjZWxlcmF0b3JFbnRpdHkiLCAibVRlc3RTdGF0dXMiOiB0cnVlLCAibVgiOiAzLjgwNDM1MTgsICJtWiI6IC0zLjM4OTU3MjF9LCB7Im1OYW1lIjogImJhcm9tZXRlckVudGl0eSIsICJtVmFsdWUiOiAwLCAibVRlc3RTdGF0dXMiOiBmYWxzZX1dLCAibUF1dG9tYXRpY1Rlc3RDb21wbGV0ZWQiOiB0cnVlfQ=='
to put in the command line, and then decode it back from base64 into JSON.
Or, even better, use:
$ your_other_program >output_file.tmp
$ python main.py < output_file.tmp
$ rm output_file.tmp

Ok so here is what is my test script:
print("original sys.argv output\n" + (sys.argv[1]))
string_temp=(yaml.load(sys.argv[1]))
print ("first transformation\n" +string_temp)
string_temp=string_temp.replace(":",": ")
dict_in=yaml.load(string_temp)
print("This is the dictionary")
print(dict_in)
This is what I type into the console
python test_script.py """{foo:bar, id:23}"""
And This is the output
original sys.argv output
"{foo:bar, id:23}"
first transformation
{foo:bar, id:23}
This is the dictionary
{'foo': 'bar', 'id': 23}
This only workds if I use tripple quotes ("""). If I use (") or (') to define the input string I get an error.
Alternatively one can remove the (") from the sys.argv[1]
print("original sys.argv output\n" + (sys.argv[1]))
string_temp=(sys.argv[1])[1:-1]
print ("first transformation\n" +string_temp)
string_temp=string_temp.replace(":",": ")
dict_in=yaml.load(string_temp)
print("This is the dictionary")
print(dict_in)

Related

What is wrong with my Python syntax: I am trying to use multiple quotation marks plus variables in a string

I am trying to use Python to write to a file. However, the code has multiple " in it plus calls a variable. I simply cannot manage the syntax.
The code should result in:
{
"Name of site": "https://.google.com",
Where the website is a variable not a string.
The code attempt is below. It never resolves the variable and just displays it as a string called host_name. I have attempted to add backslashes and quotations (various types of single and double) but whatever I try does not work.
with open ("new_file.txt", "a") as f:
f.write ("{ \n")
f.write("\"Name of site\": \"https://" + host_name + ", \n")
The new_file.txt shows:
"Name of site": "https:// + host_name + "\," + "
I have no idea where the "\," comes from.
You can use f strings, and take advantage of the fact that both '' and "" create string literals.
>>> host_name = example.com
>>> output = "{\n"+ f'"Name of site": "https://{host_name}",' + "\n"
>>> print(output)
{
"Name of site": "https://example.com",
Note that in that example you have to also concatenate strings in order to avoid the fact that f-strings don't allow either braces or backslashes; however, there is even a way around that.
newline = '\n'
l_curly = "{"
output = f'{l_curly}{newline}"Name of site": "https://{host_name}", {newline}'
So that's how you'd build the string directly. But it does also seem more likely that what you really want to is to construct a dictionary, then write that dictionary out using JSON.
>>> import json
>>> host_name = 'example.com'
>>> data = {"Name of site": f"https://{host_name}"}
>>> output = json.dumps(data, indent=4)
>>> print(output)
{
"Name of site": "https://example.com"
}

Parse argument to JSON string in python

I want to do following in my python script:
d = {"dpid": + sys.argv [1] + ,"flow_id" : "flow0001"," "actions":{"output":2}}
Its a JSON string further I am loading in my application, can any help, how should I parse that argument in the string ?
Your code is incorrect. Replace it with:
d = "{\"dpid\":" + sys.argv[1] + ",\"flow_id\":\"flow0001\",\"actions\":{\"output\":2}}"
Make sure the argument you type is an integer. If you want to parse the json string and get the dpid later, write this (python 3 code):
import json
j = json.loads(d)
print(j['dpid'])
If your file name is test.py
Then
pass args like below
$ python test.py arg1 arg2 arg3
in test.py file you can access them as string by str(sys.argv[index])
in your scenario
d = '{"dpid":"' + str(sys.argv [1]) +'" ,"flow_id":"flow0001", "actions":{"output":2}}'
then parse that string as below,
import json
obj = json.loads(d)

removing space from string in python

def digits_plus(test):
test=0
while (test<=3):
print str(test)+"+",
test = test+1
return()
digits_plus(3)
The output is:
0+ 1+ 2+ 3+
However i would like to get: 0+1+2+3+
Another method to do that would be to create a list of the numbers and then join them.
mylist = []
for num in range (1, 4):
mylist.append(str(num))
we get the list [1, 2, 3]
print '+'.join(mylist) + '+'
If you're stuck using Python 2.7, start your module with
from __future__ import print_function
Then instead of
print str(test)+"+",
use
print(str(test)+"+", end='')
You'll probably want to add a print() at the end (out of the loop!-) to get a new-line after you're done printing the rest.
You could also use the sys.stdout object to write output (to stdout) that you have more fine control over. This should let you output exactly and only the characters you tell it to (whereas print will do some automatic line endings and casting for you)
#!/usr/bin/env python
import sys
test = '0'
sys.stdout.write(str(test)+"+")
# Or my preferred string formatting method:
# (The '%s' implies a cast to string)
sys.stdout.write("%s+" % test)
# You probably don't need to explicitly do this,
# If you get unexpected (missing) output, you can
# explicitly send the output like
sys.stdout.flush()

Print python os.urandom output on terminal

how can i print the output of os.urandom(n) in terminal?
I try to generate a SECRET_KEY with fabfile and will output the 24 bytes.
Example how i implement both variants in the python shell:
>>> import os
>>> out = os.urandom(24)
>>> out
'oS\xf8\xf4\xe2\xc8\xda\xe3\x7f\xc75*\x83\xb1\x06\x8c\x85\xa4\xa7piE\xd6I'
>>> print out
oS�������5*������piE�I
If what you want is hex-encoded string, use binascii.a2b_hex (or hexlify):
>>> out = 'oS\xf8\xf4\xe2\xc8\xda\xe3\x7f\xc75*\x83\xb1\x06\x8c\x85\xa4\xa7piE\xd6I'
>>> import binascii
>>> print binascii.hexlify(out)
6f53f8f4e2c8dae37fc7352a83b1068c85a4a7706945d649
To use just built-ins, you can get the integer value with ord and then convert that back to a hex number:
list_of_hex = [str(hex(ord(z)))[2:] for z in out]
print " ".join(list_of_hex)
If you just want the hex list, then the str() and [2:] are unnecessary
The output of this and the hexify() version are both type str and should work fine for the web app.

Getting a list by sys.argv

I pass mylist as an argument to be get after by sys.argv I do this:
mylist = str(list)
nbre = str(nbre)
comm = 'python2.6 file.py ' + mylist + ' ' + nbre + ' &'
os.system(comm)
In file.py, I am expected to get mylist by this way and which contains [machine1,machine2] but when doing:
mylist = sys.argv[1]
I get [machine1, which is wrong. When I display sys.argv I found:
['file.py','[machine1,','machine2]','1']
I didn't understand why my list is composed like that?
Apart from this being a terrible way to communicate a list from one python script to another, you'd need to use quotes around the list to prevent it from being split by the shell:
comm = 'python2.6 file.py "%s" "%s" &' % (mylist, nbre)
I've used string formatting to put the quotes around mylist and nbre.
You really want to look into the subprocess module to invoke other processes without the shell getting in the way.

Categories