question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Python: Unable to loop if key.value() is Null

See original GitHub issue

I am working on a use case to remove the “All Users” group from a folder, and I am using all_content_metadata_accesses.

In Looker, if a folder doesn’t have any groups as its editor or viewer, then group_id is null (json), so I expect to loop and write some conditions with group_id, similar to this:

testing_loop = [{'a':1, 'group_id': None }, {'a':1, 'group_id':1}]  
for i in testing_loop:
  if i['group_id'] is not None:
    print('group_id is not Null')
  else: 
    print('group_id is Null')

However, I am unable to loop or do anything with the key-value pair ‘group_id’ if the value is None because we have an exception handling a key with a None value:

accesses = sdk.all_content_metadata_accesses(content_metadata_id=767)
test_dict = accesses[0] # Purposely choose accesses[0] because I know group_id here is Null 
print(type(test_dict))
print(test_dict['id']) # OK
print(test_dict['group_id']) # KeyError: 'group_id'
__getitem__(self, key)
     63             ret = ret.value
     64         if ret is None:
---> 65             raise KeyError(key)
     66         return ret
     67 

KeyError: 'group_id'

I’ll post a reproduction case in our internal tool.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
joeldodge79commented, Aug 9, 2021

TLDR; I believe the if ret is None: raise KeyError(key) logic is wrong and I’ll see about removing it.

also sorry I missed the notification

this is more complicated. This “dictionary” access is a facade in front of the actual model/instance interface the python sdk presents.

When we wrote the initial [de]serialization for the model/instance interface we hit a snag where we if someone wrote this and sent it:

user = User(first_name="Jill")

we would send null for all unspecified json properties:

{"first_name": "Jill", "last_name": null, ...}

In order to work around this we decided to remove all None properties from a model before serializing it so the resulting json would only have what you specified. In the rare case that you meant to send a json null, then you’d do:

user = User(first_name="Jill", last_name=EXPLICIT_NULL) # defined in models.py

But that’s all about creating input to be sent to the API. Here we’re really talking about a response object/dict (though keeping in mind that often the response obj/dict is re-used as input). I think we should NOT be raising a KeyError if the field is None.

This raises another question that is applicable to both the model/instance and dictionary interfaces: for a sparse response (e.g. fields parameter was used on the api call) how can we distinguish between a field missing from the json payload versus one that is present and the value is null?

We currently don’t distinguish when we populate a response model/instance and, because the dictionary implementation is just a proxy to the model/instance, then we should expose what it would do. It’s gonna look kind of odd though:

user = User()
user.first_name  # None
user['first_name']  # None
1reaction
josephaxisacommented, Aug 9, 2021

@lanlooker sorry for the delay on this, I missed the notification. The behavior you’re experiencing is not unique to the SDK unfortunately; accessing a dictionary item that does not exist throws a KeyError in Python. However, I can think of a couple of ways to get around this. Consider the below dictionary:

x = { 'foo': 'foo_val' }
  1. Use the in operator to check if the key exists before accessing it
if 'bar' in x:
  print(x['bar'])
  1. Use dict.get(key[, default]) (docs)
print(x.get('foo')) # foo_val
print(x.get('bar', None)) # None
print(x.get('bar', 'N/A')) # N/A
print(x.get('bar')) # None

Hope this helps!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Python Loop iteration with replacement of null values in ...
Show activity on this post. I need to replace null values with value of the list below in Python. Value will be same...
Read more >
Check if a Key (or Value) Exists in a Dictionary (5 Easy Ways)
Learn how to use Python to check if a key (or a value) exists in a dictionary in a safe way, using the...
Read more >
Supported PL/pgSQL statements - Amazon Redshift
The no-op statement ( NULL; ) is a placeholder statement that does nothing. A no-op statement can indicate that one branch of an...
Read more >
ProjPython – Lists and for-loops - Project Python
After adding, we get 20, and assign that value to the 0th item of the list. Run the program to see the result....
Read more >
Python Dictionary (Dict) Tutorial - AskPython
Python Dictionary is a set of key-value pairs. A dictionary is an object of dict class. We can iterate using Dictionary keys and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found