Python中通过dict.get(xxxx,'None')获取字典数据,为什么会出现时有时无的情况?
就是我一开始定义了一个 session = {},紧接着通过 session['a'] = 1 的方式给字典赋值, 然后在 get 的过程中,出现了有时候拿到了数据,有时候返回 None 的情况,不得其解。 麻烦大家了,先感谢各位的解答。
Python中通过dict.get(xxxx,'None')获取字典数据,为什么会出现时有时无的情况?
有代码吗?
这个问题的核心在于你混淆了字符串 'None' 和 Python 关键字 None。
dict.get(key, default) 方法的第二个参数是当键不存在时返回的默认值。当你写 dict.get(xxxx, 'None') 时,你设置了一个字符串 'None' 作为默认值。这意味着无论字典里有没有 xxxx 这个键,你永远不会得到 None 这个对象。如果键不存在,你得到的是字符串 'None';如果键存在但它的值就是 None,你得到的也是 None。
你感觉到的“时有时无”,很可能是因为字典里 xxxx 键对应的值本身就是 None(所以你得到了 None),或者在某些情况下这个键根本不存在(所以你得到了字符串 'None')。这两个结果在打印或进行逻辑判断时表现完全不同。
正确的做法应该是:
my_dict = {'a': 1, 'b': None}
# 错误:永远返回字符串 'None' 或实际值
result_wrong = my_dict.get('c', 'None') # 返回字符串 'None'
print(result_wrong, type(result_wrong)) # 输出: None <class 'str'>
# 正确:不传第二个参数,键不存在时默认返回 None 对象
result_correct = my_dict.get('c') # 键'c'不存在,返回 None
print(result_correct, type(result_correct)) # 输出: None <class 'NoneType'>
# 或者明确使用 None 作为默认值(和不传效果一样)
result_also_correct = my_dict.get('c', None) # 同样返回 None 对象
简单总结: 想要在键不存在时返回 None,直接使用 dict.get(key) 或不带第二个参数即可,别画蛇添足加个引号。
>>> s ={}
>>> s[‘a’]=None
>>> s[‘b’]=1
>>> s.get(‘a’,‘None’)
>>> print s.get(‘a’,‘None2’)
None
>>> print s.get(‘b’,‘None2’)
1
>>> print s.get(‘c’,‘None2’)
None2
“None” --> None
这是类的外部定义的
global session
session = {}
紧接着
类的内部的某个函数
global session
openid = json_data.get(‘openid’,‘None’)
tupl = get_3rd_session(openid)
rdSession = tupl[1].decode()
session[rdSession] = openid #看这一句跟第一句就好了
最后在另外一个类的某个函数里面调用的时候是这样的
global session
openid = session.get(rdSession,‘None’)
理论上讲应该是能获取到这个 openid 的,但是却出现了有时拿到了有时拿不到的情况。百思不得其解
#4
1. 建议你在赋值之前 print 这两个: openid, rdSession 键值对, 确定你的 rdSession 存在于这个 dict 中.
2. 大量重复使用 global session, 似乎不是一个好方法, 如果它不是可变的对象, 建议在类的构造方法中这样写:
def init(self, session)
…self.session = session
谢谢你的回答。不过我确实是把 key 以及对应的 value 加进去了,但是在不断的获取的过程中出现了有时候这个 key 存在,有时候又不存在的情况,我不太清楚是什么原因。
其实我是最近在写一个微信小程序的项目,在登录的时候需要通过一个随机串来判断对应的 openid 是否存在,这个 rdSession 就是随机串,跟 openid 形成键值对。
我在每次将 rdSession 返回给前端的时候,都会将其写入 session 中,之后调用接口的时候就利用 rdSession 来判断是谁调用了接口,再返回数据。
最后就是卡在了这个地方,每次 session.get()来寻找是哪个用户的时候,有时候就找不到了,有时候却可以,很是纳闷。
不好意思,不太明白你的意思。
可能性一:存取的 session 不是同一个 session。
可能性二:存取的键 rdSession 不是同一个值。
试着在每次 session 存取时:
print(id(session)
print(repr(rdSession))
检查是否一致。
#9
他的意思是这个:
session = {‘a’: 1}
b1 = session.get(‘b1’, ‘None’)
b2 = session.get(‘b2’, None)
>>>print(b1, b2)
None None
>>>print(type(b1), type(b2))
<class ‘str’> <class ‘NoneType’>
推测,在函数获取前又走了一遍 python<br>global session<br>session = {}<br>
建议追踪一个这个 session 变量
恭喜你,有时有,有时无,大概率是数据竞态。
单节点可以通过减少全局变量,读写锁来规避。
多节点的话,用 memcache、redis 之类的保证。
集群的话,shard+version (乐观锁)能基本保证。
再向上我没有碰到过了,欢迎讨论。
你要不每次 get 之前先 print 出来吧,现在我们也不知道你的上下文,你说的只需要看某一段代码有点不妥。
上网查了一些相关资料,不是很明白怎么跟踪。不知道前辈能不能讲一下大概。
我把相关代码都贴上了,劳烦看一下了。
不好意思,我把部分相关的代码贴上了,能麻烦你看一下吗?
那你这个服务是如何 run 起来的呢?看起来有可能是多进程模型的问题。
1. 跟踪这个问题的关键是, 输出的这个字典, 我观察到:
openid = session.get(rdSession,None) # Todolist 类, get 方法中, 字典的访问操作 F1
openid = session.get(rdSession,None) # Todolist 类, post 方法中, 字典的访问操作 F2
session[rdSession] = openid # Session3d 类中, get 方法中, 字典的修改操作 F3
因此你要在这个三个地方, 输出这个字典. 尤其是修改操作的前后的变化, 要跟踪其中的值.
2. 追踪这个 dict 的值有两种方式, 如果你是开发环境, 可以直接 print 出来, 或者用 logging 模块. 下面是:
logging 的方式:
# Logging 配置
logger = logging.getLogger(‘my_logger’)
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler(filename=‘我的小程序日志.log’)
formatter = logging.Formatter(’%(asctime)s %(filename)s[line:%(lineno)d] ’ +
‘%(levelname)s %(message)s’)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
然后在 F1, F2 的地方: logging.info(str(session)),
在 F3 的代码的上下行 : logging.info(str(session)),
3. Todolist 中只有字典的访问的操作, 似乎不需要使用 global 关键字也可以
这个是放在服务器上跑的。
不好意思,请问放到代码中的时候是这样子吗?
’’’
…上面的代码省略
import logging
logger = logging.getLogger(‘my_logger’)
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler(filename=‘我的小程序日志.log’)
formatter = logging.Formatter(’%(asctime)s %(filename)s[line:%(lineno)d] ’ +
’%(levelname)s %(message)s’)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
class Todolist(Resource):
#用户进入页面后将该用户所有的待办事项返回给前端渲染到页面
def get(self,rdSession):
global session
logging.info(str(session))
openid = session.get(rdSession,None) #通过前端发送过来的随机串 key 得到对应的 value
logging.info(str(session))
请问楼主这个代码是多进程方式部署的么?
重要的事情说三遍:
每个进程中的变量是相互隔离的。
每个进程中的变量是相互隔离的。
每个进程中的变量是相互隔离的。
进程是并发执行的,进程之间默认是不能共享全局变量的。如果要共享全局变量需要用
( multiprocessing.Value(“d”,10.0),数值)
( multiprocessing.Array(“i”,[1,2,3,4,5]),数组)
( multiprocessing.Manager().dict(),字典)
( multiprocessing.Manager().list(range(5)))。
进程通信(进程之间传递数据)用进程队列( multiprocessing.Queue(),单向通信),
管道( multiprocessing.Pipe() ,双向通信)。
或者用个 redis 服务来保存 kv
这是个 flask 服务吗 ==


