Python 如何处理 AttributeError: 'NoneType' 对象在大字典中没有属性 'get'

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21160181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:12:18  来源:igfitidea点击:

How to handle AttributeError: 'NoneType' object has no attribute 'get' in big dictionary

pythontwitterdictionarypymongo

提问by Apoorv Ashutosh

I have a big dictionary that stores the data in a tweet. Many fields in this have value Noneor Null. When I use get()function, I get an AttributeError: 'NoneType' object has no attribute 'get'.

我有一个大字典,可以将数据存储在推文中。此中的许多字段都具有值Noneor Null。当我使用get()函数时,我得到一个AttributeError: 'NoneType' object has no attribute 'get'.

My dictionary is quite large and it is not possible to handle each case individually. Any ideas on how to do this? My code is:

我的字典很大,不可能单独处理每个案例。关于如何做到这一点的任何想法?我的代码是:

from twython import TwythonStreamer
import json
from pymongo import MongoClient
import os
from datetime import *
client = MongoClient()
db1 = client.PWSocial
db2 = client.PWSocial
db3 = client.PWSocial
db4 = client.PWSocial
APP_KEY = 'XXXXX'
APP_SECRET = 'XXXXX'
OAUTH_TOKEN = 'XXXXX'
OAUTH_TOKEN_SECRET = 'XXXXXX'
class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        self.n=self.n+1
        print self.n
        print data
        user=data.get("user")
        tweets = db1.tweets
        user_mentions = db2.user_mentions
        hash_tags = db3.hash_tags
        users = db4.users
        dict1 = {'id':data.get("id"),'contributors':data.get("contributors"),'truncated':data.get('truncated'),'text':data.get('text'),'in_reply_to_status_id':data.get("in_reply_to_status_id"),'favorite_count':data.get('favorite_count'),'source':data.get('source'),'retweeted':data.get('retweeted'),'coordinates':data.get('coordinates'),'symbols':data.get('symbols'),'urls':data.get('urls'),'in_reply_to_screen_name':data.get('in_reply_to_screen_name'),'id_str':data.get('id_str'),'retweet_count':data.get('retweet_count'),'in_reply_to_user_id':data.get('in_reply_to_user_id'),'favorited':data.get('favorited'),'geo':data.get('geo'),'in_reply_to_user_id_str':data.get('in_reply_to_user_id_str'),'lang':data.get('lang'),'created_at':data.get('created_at'),'filter_level':data.get('filter_level'),'in_reply_to_status_id_str':data.get('in_reply_to_status_id_str'),'place':data.get('place'),'user_id':user.get('user_id')}
        posts1 = db1.posts
        post_id = posts1.insert(dict1)
        um = data.get("user_mentions")
        #dict2 = {'tweet_id':data.get('id'),'id':um.get('id'),'indices':um.get('indices'),'id_str':um.get('id_str'),'screen_name':um.get('screen_name'),'name':um.get('name')}
        #posts2 = db2.posts
        #post_id2 = posts2.insert(dict2)
        ht = data.get('hashtags')
        dict3 = {'tweet_id':data.get('id'),'indices':ht.get('indices'),'text':ht.get('text')}
        posts3 = db3.posts
        post_id3 = posts3.insert(dict3)
        usr = data.get("user")
        dict4 = {'follow_request_sent':usr.get('follow_request_sent'),'profile_use_background_image':usr.get('profile_use_background_image'),'default_profile_image':usr.get('default_profile_image'),'id':usr.get('id'),'verified':usr.get('verified'),'profile_image_url_https':usr.get('profile_image_url_https'),'profile_sidebar_fill_color':usr.get("profile_sidebar_fill_color"),'profile_text_color':usr.get('profile_text_color'),'followers_count':usr.get('followers_count'),'profile_sidebar_border_color':usr.get('profile_sidebar_border_color'),'id_str':usr.get('id_str'),'profile_background_color':usr.get('profile_background_color'),'listed_count':usr.get('listed_count'),'profile_background_image_url_https':usr.get('profile_background_image_url_https'),'utc_offset':usr.get('utc_offset'),'statuses_count':usr.get('statuses_count'),'description':usr.get('description'),'friends_count':usr.get('friends_count'),'location':usr.get('location'),'profile_link_color':usr.get('profile_link_color'),'profile_image_url':usr.get('profile_image_url'),'following':usr.get('following'),'geo_enabled':usr.get('geo_enabled'),'profile_banner_url':usr.get('profile_banner_url'),'profile_background_image_url':usr.get('profile_background_image_url'),'name':usr.get('name'),'lang':usr.get('lang'),'profile_background_tile':usr.get('profile_background_tile'),'favourites_count':usr.get('favourites_count'),'screen_name':usr.get('screen_name'),'notifications':usr.get('notifications'),'url':usr.get('url'),'created_at':usr.get('created_at'),'contributors_enabled':usr.get('contributors_enabled'),'time_zone':usr.get('time_zone'),'protected':usr.get('protected'),'default_profile':usr.get('default_profile'),'is_translator':usr.get('is_translator')}
        if (datetime.now() > self.stop_time):
            self.disconnect()
    def on_error(self, status_code, data):
        print status_code
        return True # Don't kill the stream

    def on_timeout(self):
        print >> sys.stderr, 'Timeout...'
        return True # Don't kill the stream

stream = MyStreamer(APP_KEY, APP_SECRET,
                    OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
#stream.statuses.filter(follow = [57947109, 183093247, 89443197, 431336956])
stream.statuses.filter(follow = 95995660)

A sample of the dictionary I am dealing with is:

我正在处理的字典示例是:

data = {
    "contributors": null, 
    "truncated": false, 
    "text": "@mipaltan #MI4LakhStronger if i become admin,i will hold trivia based contest which will held fans refresh old memories", 
    "in_reply_to_status_id": 420452758068539392, 
    "id": 420455226563231744, 
    "favorite_count": 0, 
    "source": "<a href=\"https://mobile.twitter.com\" rel=\"nofollow\">Mobile Web (M2)</a>", 
    "retweeted": false, 
    "coordinates": null, 
    "entities": {
        "symbols": [], 
        "user_mentions": [
            {
                "id": 106345557, 
                "indices": [
                    0, 
                    9
                ], 
                "id_str": "106345557", 
                "screen_name": "mipaltan", 
                "name": "Mumbai Indians"
            }
        ], 
        "hashtags": [
            {
                "indices": [
                    10, 
                    26
                ], 
                "text": "MI4LakhStronger"
            }
        ], 
        "urls": []
    }, 
    "in_reply_to_screen_name": "mipaltan", 
    "id_str": "420455226563231744", 
    "retweet_count": 0, 
    "in_reply_to_user_id": 106345557, 
    "favorited": false, 
    "user": {
        "follow_request_sent": null, 
        "profile_use_background_image": true, 
        "default_profile_image": false, 
        "id": 87174680, 
        "verified": false, 
        "profile_image_url_https": "https://pbs.twimg.com/profile_images/378800000220301249/a0c7b8c5766de83b65a42ca52196c4b3_normal.jpeg", 
        "profile_sidebar_fill_color": "EADEAA", 
        "profile_text_color": "333333", 
        "followers_count": 348, 
        "profile_sidebar_border_color": "D9B17E", 
        "id_str": "87174680", 
        "profile_background_color": "8B542B", 
        "listed_count": 5, 
        "profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/350203578/Photo0003.jpg", 
        "utc_offset": 19800, 
        "statuses_count": 20119, 
        "description": "Sports Lover", 
        "friends_count": 708, 
        "location": "India", 
        "profile_link_color": "9D582E", 
        "profile_image_url": "http://pbs.twimg.com/profile_images/378800000220301249/a0c7b8c5766de83b65a42ca52196c4b3_normal.jpeg", 
        "following": null, 
        "geo_enabled": true, 
        "profile_background_image_url": "http://a0.twimg.com/profile_background_images/350203578/Photo0003.jpg", 
        "name": "Ronak Baj", 
        "lang": "en", 
        "profile_background_tile": true, 
        "favourites_count": 17, 
        "screen_name": "ronakbaj", 
        "notifications": null, 
        "url": null, 
        "created_at": "Tue Nov 03 12:02:56 +0000 2009", 
        "contributors_enabled": false, 
        "time_zone": "New Delhi", 
        "protected": false, 
        "default_profile": false, 
        "is_translator": false
    }, 
    "geo": null, 
    "in_reply_to_user_id_str": "106345557", 
    "lang": "en", 
    "created_at": "Tue Jan 07 07:21:52 +0000 2014", 
    "filter_level": "medium", 
    "in_reply_to_status_id_str": "420452758068539392", 
    "place": null
}

The complete traceback is:

完整的回溯是:

  File "new.py", line 51, in <module>
    stream.statuses.filter(follow = 95995660)
  File "/usr/lib/python2.7/site-packages/twython/streaming/types.py", line 65, in filter
    self.streamer._request(url, 'POST', params=params)
  File "/usr/lib/python2.7/site-packages/twython/streaming/api.py", line 148, in _request
    if self.on_success(data):  # pragma: no cover
  File "new.py", line 33, in on_success
    dict3 = {'tweet_id':data.get('id'),'indices':ht.get('indices'),'text':ht.get('text')}
AttributeError: 'NoneType' object has no attribute 'get'

PS: Please comment if any data I have given is unnecessary, and I will edit the question.

PS:如果我提供的任何数据是不必要的,请发表评论,我将编辑问题。

采纳答案by Martijn Pieters

You are trying to access the .get()method on the result data.get()calls:

您正在尝试访问.get()结果data.get()调用的方法:

ht = data.get('hashtags')

and

usr = data.get("user")

but if there is no'hashtags'or 'user'keys in the datadictionary, then either htor usris set to None, and the ht.get()or usr.get()calls fail.

但如果字典中没有'hashtags'or'user'data,则htorusr设置为None,并且ht.get()orusr.get()调用失败。

Either use a better default or guard against usrbeing None:

要么使用更好的默认值,要么避免usr成为None

ht = data.get('hashtags', {})  # return an empty dictionary if missing

and

usr = data.get('user', {})  # return an empty dictionary if missing

If it is an error for a key not to be present, don't use .get()but use direct access:

如果密钥不存在是一个错误,请不要使用.get()而是使用直接访问:

usr = data['user']

Note that your dataobject has nohashtagskey in any case. There is a hashtagskey in the data['entities']dictionary, however:

请注意,您的data对象在任何情况下都没有hashtags键。但是hashtagsdata['entities']字典中有一个键:

ht = data['entities']['hashtags']

This is a listof hashtags, so ht.get('indices')will now fail with an AttributeError: 'list' object has no attribute 'get'; you need to loop through all the different hashtags or pick onefrom the list.

这是一个主题标签列表,因此ht.get('indices')现在将失败并显示AttributeError: 'list' object has no attribute 'get'; 您需要遍历所有不同的主题标签或从列表中选择一个

回答by Apoorv Ashutosh

Am answering this one myself, based on the final solution I found.

根据我找到的最终解决方案,我自己回答了这个问题。

What @Martjin Peters said above is absolutely correct, and the tweet that was returned had no data in the hashtags dictionary under the entities dictionary, and in such a case, there was no data in ht. In such a case, the .get()function cannot be used.

@Martjin Peters上面说的完全正确,返回的tweet在entities字典下的hashtags字典中没有数据,在这种情况下,ht中没有数据。在这种情况下,.get()无法使用该功能。

However, the solution to this is simple, simply use

但是,解决这个问题很简单,只需使用

ht = data.get('hashtags', {})

Now, before the ht dictionary is used further, simply using an ifcondition will do the trick, like this

现在,在进一步使用 ht 字典之前,简单地使用if条件就可以了,就像这样

.
.
.#above code    

if um:
             dict2 = um[0]
             posts2 = db2.posts
             post_id2 = posts2.insert(dict2)
.
.
.#other code

Implement this for all such possible dictionaries, where no value may be returned. In my example, this has to be done for htand um.

为所有此类可能的字典实现此操作,其中可能不返回任何值。在我的示例中,这必须为htand完成um

Hope this helps if anyone in the future encounters a similar problem.

如果将来有人遇到类似的问题,希望这会有所帮助。