就是我一开始定义了一个 session = {},紧接着通过 session['a'] = 1 的方式给字典赋值, 然后在 get 的过程中,出现了有时候拿到了数据,有时候返回 None 的情况,不得其解。 麻烦大家了,先感谢各位的解答。
1
Rand01ph 2018-10-25 13:28:20 +08:00
有代码吗?
|
2
hand515 2018-10-25 13:43:47 +08:00
>>> 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 |
3
jasonqiao36 2018-10-25 13:51:16 +08:00 via Android
"None" --> None
|
4
danzzzz OP @Rand01ph
这是类的外部定义的 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 的,但是却出现了有时拿到了有时拿不到的情况。百思不得其解 |
5
anonymous256 2018-10-25 13:54:30 +08:00
session = {'a': 1, 'b': 2, 'c': 3}
session.get('a') 这种, 只要字典中有这个 key 是可以拿到相应的 value, 如果返回是 None, 则说明这个 key 不存在. 显然, 你"有时候返回 None 的情况", 就是因为不存在这个 key. 一般你可以对 None 这种情况进行处理, 不妨这样写: value = session.get('某个 key') if value is not None: # 获取成功 do something else: # 该 key 不存在 |
6
anonymous256 2018-10-25 14:02:44 +08:00
@danzzzz #4
1. 建议你在赋值之前 print 这两个: openid, rdSession 键值对, 确定你的 rdSession 存在于这个 dict 中. 2. 大量重复使用 global session, 似乎不是一个好方法, 如果它不是可变的对象, 建议在类的构造方法中这样写: def __init__(self, session) ....self.session = session |
7
danzzzz OP @anonymous256 谢谢你的回答。不过我确实是把 key 以及对应的 value 加进去了,但是在不断的获取的过程中出现了有时候这个 key 存在,有时候又不存在的情况,我不太清楚是什么原因。
|
8
danzzzz OP @anonymous256
其实我是最近在写一个微信小程序的项目,在登录的时候需要通过一个随机串来判断对应的 openid 是否存在,这个 rdSession 就是随机串,跟 openid 形成键值对。 我在每次将 rdSession 返回给前端的时候,都会将其写入 session 中,之后调用接口的时候就利用 rdSession 来判断是谁调用了接口,再返回数据。 最后就是卡在了这个地方,每次 session.get()来寻找是哪个用户的时候,有时候就找不到了,有时候却可以,很是纳闷。 |
9
danzzzz OP @jasonqiao36 不好意思,不太明白你的意思。
|
10
anonymous256 2018-10-25 14:14:05 +08:00
@danzzzz #7 建议采用 logging 跟踪一下键值对的变化. dict 作为 python 最强大的数据结构之一, 应该不可能出现存在这个 key 却获取不到的情况, 我觉得唯一的可能是你对这个 key 最后一次的赋值了 None.
d = {} d['1'] = 1 d['1'] = None print(d.get('1')) |
11
Sylv 2018-10-25 14:17:30 +08:00 via iPhone
可能性一:存取的 session 不是同一个 session。
可能性二:存取的键 rdSession 不是同一个值。 试着在每次 session 存取时: print(id(session) print(repr(rdSession)) 检查是否一致。 |
12
anonymous256 2018-10-25 14:18:47 +08:00
@danzzzz #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'> |
13
Hstar 2018-10-25 14:29:14 +08:00
推测,在函数获取前又走了一遍
``` python global session session = {} ``` 建议追踪一个这个 session 变量 |
14
mengzhuo 2018-10-25 15:03:50 +08:00
恭喜你,有时有,有时无,大概率是数据竞态。
单节点可以通过减少全局变量,读写锁来规避。 多节点的话,用 memcache、redis 之类的保证。 集群的话,shard+version (乐观锁)能基本保证。 再向上我没有碰到过了,欢迎讨论。 |
15
Yourshell 2018-10-25 15:19:47 +08:00 via iPhone
你要不每次 get 之前先 print 出来吧,现在我们也不知道你的上下文,你说的只需要看某一段代码有点不妥。
|
16
danzzzz OP @anonymous256 上网查了一些相关资料,不是很明白怎么跟踪。不知道前辈能不能讲一下大概。
|
18
danzzzz OP @anonymous256 不好意思,我把部分相关的代码贴上了,能麻烦你看一下吗?
|
20
anonymous256 2018-10-25 16:04:46 +08:00
@danzzzz
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 关键字也可以 |
22
danzzzz OP @anonymous256 不好意思,请问放到代码中的时候是这样子吗?
''' ....上面的代码省略 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)) |
23
xpresslink 2018-10-25 17:46:54 +08:00
请问楼主这个代码是多进程方式部署的么?
重要的事情说三遍: 每个进程中的变量是相互隔离的。 每个进程中的变量是相互隔离的。 每个进程中的变量是相互隔离的。 进程是并发执行的,进程之间默认是不能共享全局变量的。如果要共享全局变量需要用 ( 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 |
24
vipppppp 2018-10-26 09:46:08 +08:00
这是个 flask 服务吗 ==
|