102

I have a bytes type object like this:

b"{'one': 1, 'two': 2}"

I need to get proper python dictionary from the above bytes type object using python code.

string = b"{'one': 1, 'two': 2}"
d = dict(toks.split(":") for toks in string.split(",") if toks)

But I am getting the below error:

------> d = dict(toks.split(":") for toks in string.split(",") if toks)
TypeError: 'bytes' object is not callable
4
  • 1
    No need to make you own dictionary parser. Send the string to ast.literal_eval Commented Mar 9, 2018 at 0:08
  • The code you've posted here does not raise that exception. In fact, it does almost what you say you want it to do (modulo some mistakes in dealing with quote characters—e.g., you're going to end up with a key like " 'two'" instead of "two"). Commented Mar 9, 2018 at 0:13
  • 1
    Meanwhile, where did this input come from? Taking the repr of a Python dict and encode-ing it to UTF-8 is really not a good way to store data that you want to load back in later. Much better to use something like JSON or Pickle. Commented Mar 9, 2018 at 0:14
  • 1
    @Aran-Fey bytes is different with strings Commented Nov 17, 2021 at 3:09

4 Answers 4

145

I think a decode is also required to get a proper dict.

a= b"{'one': 1, 'two': 2}"
ast.literal_eval(a.decode('utf-8'))
**Output:** {'one': 1, 'two': 2}

The accepted answer yields

a= b"{'one': 1, 'two': 2}"
ast.literal_eval(repr(a))
**output:**  b"{'one': 1, 'two': 2}"

The literal_eval hasn't done that properly with many of my code so I personally prefer to use json module for this

import json
a= b"{'one': 1, 'two': 2}"
json.loads(a.decode('utf-8'))
**Output:** {'one': 1, 'two': 2}
Sign up to request clarification or add additional context in comments.

Comments

59

All you need is ast.literal_eval. Nothing fancier than that. No reason to mess with JSON unless you are specifically using non-Python dict syntax in your string.

# python3
import ast
byte_str = b"{'one': 1, 'two': 2}"
dict_str = byte_str.decode("UTF-8")
mydata = ast.literal_eval(dict_str)
print(repr(mydata))

See answer here. It also details how ast.literal_eval is safer than eval.

1 Comment

seems need extra decode. error log: raise ValueError('malformed node or string: ' + repr(node)) ValueError: malformed node or string: b"{'one': 1, 'two': 2}"
20

You could try like this:

import json
import ast

a= b"{'one': 1, 'two': 2}"
print(json.loads(a.decode("utf-8").replace("'",'"')))

print(ast.literal_eval(a.decode("utf-8")))

There are the doc of module:

1.ast doc

2.json doc

Comments

6

You can use Base64 library to convert string dictionary to bytes, and although you can convert bytes result to a dictionary using json library. Try this below sample code.

import base64
import json


input_dict = {'var1' : 0, 'var2' : 'some string', 'var1' : ['listitem1','listitem2',5]}

message = str(input_dict)
ascii_message = message.encode('ascii')
output_byte = base64.b64encode(ascii_message)

msg_bytes = base64.b64decode(output_byte)
ascii_msg = msg_bytes.decode('ascii')
# Json library convert stirng dictionary to real dictionary type.
# Double quotes is standard format for json
ascii_msg = ascii_msg.replace("'", "\"")
output_dict = json.loads(ascii_msg) # convert string dictionary to dict format

# Show the input and output
print("input_dict:", input_dict, type(input_dict))
print()
print("base64:", output_byte, type(output_byte))
print()
print("output_dict:", output_dict, type(output_dict))

enter image description here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.