I have the following Python dict. I'm trying to do a check with n if statement that payload contains "token"
{'payload': {'token': '3u4td7393493d9304'}, 'type': 'send'}
Below is the python code
if message['payload'] == 'token':
print("GOT IT");
print(message)
elif message['payload']['type'] == 'timedout':
print("TIMEDOUT!")
elif message['payload'] == 'locked':
print("LOCKED!")
done.set()
The current if statement for token is wrong. What is the proper way of checking if payload has "token" inside it?
To check whether a dictionary d contains key k, use k in d:
message = {'payload': {'token': '3u4td7393493d9304'}, 'type': 'send'}
# {'payload': {'locked': 'lockId'}, 'type': 'send'}
if 'token' in message['payload']:
print("GOT IT");
print(message)
print(f"token: {message['payload']['token']}")
elif message['type'] == 'timedout':
print("TIMEDOUT!")
elif 'locked' in message['payload']:
print("LOCKED!")
print(f"locked value: {message['payload']['locked']}")
# done.set()
Since you have nested dictionaries, message['payload'] is itself a dictionary, therefore to check whether it has key 'token', you have to use 'token' in message['payload'].
I've also added an example that demonstrates how to access the value that corresponds to the key 'token'.
Side note: this if-else does not seem to be exhaustive, and it lacks the default case. Maybe you should approach it a bit more systematically, and first make sure that you deal with every possible type of the message, and then for each type deal with each kind of payload.
The way i understand your question is you want to find whether or not 'token' exist in payload, regardless of the token value?
If yes, simple in array would suffice:
dc = {'payload': {'token': '3u4td7393493d9304'}, 'type': 'send'}
'token' in dc['payload'] # this would result in True
Just create a function which return True or False , now whenever you want to check pass value to that function and check :
def check_token(data_):
if 'token' in data_['payload']:
return True
else:
return False
Now back to your code , you can simply check by passing value to this function :
if check_token(data)==True:
print("GOT IT")
output:
GOT IT
Related
I am writing a piece of software that checks the input to a function before passing it to a database. To do this I need to check the type of data before I send it. Right now I am using 5 different if/else statements. How can I condense this and make it easier to read? Thank You!
def addUser(USERNAME, PASSWORD, PHONE, CARRIER, SERVER):
good = True
if type(USERNAME) == str and good:
good = True
else:
good = False
if type(PASSWORD) == str and good:
good = True
else:
good = False
if type(PHONE) == int and good:
good = True
else:
good = False
if type(CARRIER) == str and good:
good = True
else:
good = False
if type(SERVER) == str and good:
good = True
else:
good = False
All the conditions must be True. The most pythonic way would be two create two lists — one with the fields and one with their respective types, then compare the two lists and check if all conditions are True. This way you can add any number of fields by appending the fields and types lists. This way you will also avoid one very long statement with multiple conditions and the and operator between them
fields = [USERNAME, PASSWORD, PHONE, CARRIER, SERVER] # append new field if you want
types = [str, str, int, str, str] # append type of new field if you want
good = all(type(field)==types[i] for i, field in enumerate(fields))
Combine all the conditions into one:
good = type(USERNAME) == str and type(PASSWORD) == str and type(PHONE) == int AND type(CARRIER) == str and type(SERVER) == str
BTW, you generally shouldn't use int for phone numbers. Even though we call them phone numbers we don't perform any numeric operations on them. And putting a phone number in an int variable will lose leading zeroes.
You could loop over all of them. e.g:
def check_parameters(params: list):
for parameter in params:
if not isinstance(parameter,str):
return False
return True
def addUser(USERNAME, PASSWORD, PHONE, CARRIER, SERVER):
good = check_parameters([USERNAME, PASSWORD, PHONE, CARRIER, SERVER])
Note isinstance(Your_string, str) is preferred to `type() == '
To build on JeffUK's answer, you should also raise an error to tell the user which one is wrong if one fails the type test ("Errors should never pass silently."):
def check_parameters(params: list):
for i, parameter in enumerate(params):
if not isinstance(parameter,str):
raise ValueError(f'{parameter} in position {i} is {type(parameter)}, not string.')
return True
You then can wrap your function call in a try block to catch the error.
def addUser(USERNAME, PASSWORD, PHONE, CARRIER, SERVER):
try:
good = check_parameters([USERNAME, PASSWORD, PHONE, CARRIER, SERVER])
except ValueError as e:
print(e)
If you are using Python 3.10, a match-case statement might work well for your particular code.
You could also try putting the valid input types into a dictionary, which could condense the code by eliminating the else statements. e.g.,
data_type_check = {'username': str, 'password': str, 'phone': int,
'carrier': str, 'server': str}
for var, key in zip([USERNAME, PASSWORD, PHONE, CARRIER, SERVER],
['username', 'password', 'phone', 'carrier', 'server']):
good = type(var) == data_type_check[key]
if not good:
break
or even simpler
for var, vartype in zip([USERNAME, PASSWORD, PHONE, CARRIER, SERVER],
[str, str, int, str, str]):
good = type(var) == vartype
if not good:
break
How can I create python function which is able to get specific value from json based on provided arguments? The number of provided arguments should be optional as I cannot know in advance how deep into the json structer I will need to go for the value.
def json_get_value(respond, *args):
try:
my_json = json.loads(respond)
except:
print("Unable to load JSON")
return "Error ..."
try:
value = my_json[args[0]][args[1]][args[2]]
return value
except KeyError:
return "None"
answer = json_get_value(respond, "count_categories", 0, "total", ........)
My question is how I can change this line:
value = my_json[args[0]][args[1]][args[2]....]
so the function will be universal for any number of arguments and so for any number of keys to get the desired value. I know that in case with *args is often used a for cycle, but in this case I am not sure how to utilize for cycle for this purpose.
Thanks a lot for any help.
A possible solution is to use your variable value to keep the current level in the JSON tree in which you are:
try:
value = my_json
for arg in args:
value = value[arg]
return value
except KeyError:
return "None"
Note that, if no args are passed, this function simply returns the parsed json file.
you could use a recursive function for this. So if you still have args then keep drilling into the json. If you have a key in your args list thats not in the JSON then return a None object, otherwise keep drilling down until you get the data
jdata = {
"foo": 1,
"bar": 2,
"nest1": {
"baz": "bar"
},
"nest2": {
"nest3": {
"nest4": {
"hello": "world"
}
}
}
}
def get_from_json(jdata: dict, *keys):
try:
data = jdata[keys[0]]
except KeyError:
return None
if len(keys) > 1:
return get_from_json(data, *keys[1:])
return data
print(get_from_json(jdata, "nest2", "nest3", "nest4", "hello"))
print(get_from_json(jdata, "nest1"))
print(get_from_json(jdata, "nest2", "nest3"))
print(get_from_json(jdata, "val", "boo"))
print(get_from_json(jdata, "nest2", "nest3", "someval"))
OUTPUT
world
{'baz': 'bar'}
{'nest4': {'hello': 'world'}}
None
None
#authenticated decorator allows the function to run is user1 has 'valid' set to True:
user1 = {
'name': 'Sorna',
'valid': False #changing this will either run or not run the message_friends function.
}
def authenticated(fn):
def wrapper(*args , **kwargs):
if args[0]['valid']:
fn(*args, **kwargs)
else:
print(f'You are not authenticated to send messages. Please make deposit of $5 to your account')
return wrapper
#authenticated
def message_friends(user):
print('message has been sent')
message_friends(user1)
I am having troubles understanding why args[0]['valid'] is used. When I used args[1]['valid] I got error,
I know i'm missing some key concept. please help me out here
For def wrapper(*args , **kwargs) -> args represents the dictionary (user1), the if statement takes the dictionary (args[0]) and then takes the key 'valid' (args[0]['valid']), this way if the content of the key 'valid' is False you won't send the message (else statement) and if the content is True you will send the message.
Try changing the content of the valid key as follow:
user1 = {'name': 'Sorna','valid': True}
Under these circumstances, the message will be sent.
I got stuck before on this one too, but I assume that should be the right answer:
args is passed to the function as tuple. In that case a tuple that has only one item (the user1 dictionary).
Something like this:
args = ({user1})
In order to access the key ['valid'], you need to indicate first that you are accessing the first item in the tuple [0].
I expanded the code a bit: added another user and created for loop inside the authenticator to check throught the whole args tuple to check for the ['valid'] in as many users as you would like to input in the message function. It only returns the message if all the users have the 'valid' key set to True. If any item of the tuple args has the key set to False, the wrapper function returns None inside the if statement, not reaching the function to be called after the for loop
user1 = {'name': 'Sorna', 'valid': True}
user2 = {'name': 'Ivan', 'valid': True}
def authenticated(fn):
def wrapper(*args, **kwargs):
for i in range(len(args)):
if not args[i]['valid']:
return None
return fn(*args, **kwargs)
return wrapper
#authenticated
def message_friends(*args):
print('message has been sent')
message_friends(user1, user2)
I am implementing a chat client gui whith server-push functionality. The messages that will be sent will look like this:
yourMessage = {'name': 'David', 'text': 'hello world'}
I recieve a server-push by a call to the streamHandler
def streamHandler(incomingData):
if incomingData["event"] == "put":
if incomingData["path"] == "/":
if incomingData["data"] != None:
for key in incomingData["data"]:
message = incomingData["data"][key]
handleMessage(message)
else:
message = incomingData["data"]
handleMessage(message)
Then I have the function handleMessage that should retrieve the values of name and text:
def handleMessage(message):
for key in message.values():
printToMessages(key)
But now I get this Error: 'str' object has no attribute 'values' I have tried making message to dict but with no success, any ideas?
Perhaps the message parameter is a json string.
If so you can have:
import json
def handleMessage(text):
message = json.loads(text)
for key in message.values():
printToMessages(key)
I`m doing an unit test for the first time and I need to check if a success key is the same as the other one, how can I check a success key without checking the whole dictionary?
I just need to check the success key not all the other ones
I need to do it with assert using the unit test module
dict 1 = {'success': RC.input_validation,
'return_msg': return_msg,
'debug_data': debug_data}
dict 2 = {'success': RC.success,
'return_msg': return_msg,
'debug_data': debug_data}
class MyTestCase(unittest.TestCase):
def test_something(self):
call_result = {}
debug_data = []
test = SetShape()
call_result = SetShape.setShape(test, shapechoosing=1)
debug_data.append(call_result)
print("10")
if __name__ == '__main__':
unittest.main()
Access the values of the 'success' key in each dictionary and check if they're equal
if dict1['success'] == dict2['success']:
print("they're the same")
This should work for you.
dict_1 = {'success': "RC.input_validation",
'return_msg': "return_msg",
'debug_data': "debug_data"}
dict_2 = {'success': "RC.success",
'return_msg': "return_msg",
'debug_data': "debug_data"}
dict_1.get('success')==dict_2.get('success')
Is this what you're looking for?
if dict_1.get('success') == dict_2.get('success'):
# your body of code
Hope it helps!!