Python类变量在Django应用程序中表现异常

我已经在Django中创建了一个REST API视图,以跟踪谁正在输入客户端聊天程序,因此我可以通过动画图标通知聊天通道中的其他用户。

在客户端,只要用户输入,此视图就会每2秒钟收到一次POST呼叫(一种“ ping”呼叫)。如果用户停止输入超过2秒钟,这些ping便会停止输入。

在服务器端,如您在此视图中所见,我保留了current_typists的列表,该列表由聊天的channel_idtypist_id索引。此列表包含5秒计时器,每个打字员一个。每当执行ping操作时,计时器就会延长。如果5秒钟内没有ping操作,计时器将耗尽,并且可以通知另一位打字员打字已停止。

我将current_typiststyping_lock都存储为类变量,以确保对这些计时器的异步访问不会冲突。

@authentication_classes((TokenAuthentication,))
class ChatUserIsTypingView(APIView):
    
    current_typists = {}
    typing_lock = Lock()

    # Notify the other user silently whether typist_id is typing or not
    def notify_typing_status(self,typist_id,other_id,typing):
        do_the_notification_here()

    # When a timer has elapsed after 5 seconds,remove it.
    def chat_user_stopped_typing(self,channel_id,notify=True):
        self.typing_lock.acquire()
        print("Timer",self.current_typists[(channel_id,typist_id)],"elapsed. REMOVING.")
        self.current_typists.pop((channel_id,typist_id))
        print("AFTER REMOVAL,keys =",self.current_typists.keys())
        if notify:
            self.notify_typing_status(typist_id,False)
        self.typing_lock.release()
    
    # We receive this 'ping' every two seconds from the client while a user is typing
    def post(self,request,format=None):
        channel_id = request.data['channel_id']
        typist_id = request.user.id
        other_id = request.data['other_id']
    
        self.typing_lock.acquire()
        already_typing = (channel_id,typist_id) in self.current_typists
        if not already_typing:
            print("NO current timer,keys:",self.current_typists.keys())
            self.notify_typing_status(typist_id,True)
        else:
            print("CANCELING timer",typist_id)])
            self.current_typists[(channel_id,typist_id)].cancel()
            self.current_typists.pop((channel_id,typist_id))
            print("CANCELED timer,self.current_typists.keys())
        typing_sample_period = 5
        t = Timer(typing_sample_period,self.chat_user_stopped_typing,args=[channel_id,True])
        self.current_typists[(channel_id,typist_id)] = t
        t.start()
        print("STARTED timer",t,"keys:",self.current_typists.keys())
        self.typing_lock.release()
    
        return Response({},status=status.HTTP_200_OK)

这可能比必要的背景要多,但是上下文可能会有所帮助。

这是实践中发生的事情。它可以工作,但是有时会通知用户键入已经停止,然后才真正停止。我用这些打印语句对代码进行了检测,以查看发生了什么。

2020-08-06T22:20:05.710264+00:00 app[web.1]: NO current timer,keys: dict_keys([])
2020-08-06T22:20:06.502792+00:00 heroku[router]: at=info method=POST path="/notifications/chat_user_is_typing/" host=ridehare.herokuapp.com request_id=ae3f9e37-0bad-4333-8294-f4e639c4c970 fwd="172.91.141.66" dyno=web.1 connect=1ms service=1067ms status=200 bytes=218 protocol=https
2020-08-06T22:20:06.498288+00:00 app[web.1]: STARTED timer <Timer(Thread-18,started 140708212107008)> keys: dict_keys([('OCsHYT3eiHV0PBbJDCPZ',51)])
2020-08-06T22:20:06.502453+00:00 app[web.1]: 10.63.103.37 - - [06/Aug/2020:15:20:06 -0700] "POST /notifications/chat_user_is_typing/ HTTP/1.1" 200 2 "-" "RideHare/0.1 (com.ridehare.RideHare; build:4716; iOS 13.6.0) Alamofire/5.2.2"
2020-08-06T22:20:08.915502+00:00 app[web.1]: NO current timer,keys: dict_keys([])
2020-08-06T22:20:09.641035+00:00 app[web.1]: STARTED timer <Timer(Thread-18,started 140708161779456)> keys: dict_keys([('OCsHYT3eiHV0PBbJDCPZ',51)])
2020-08-06T22:20:09.645318+00:00 app[web.1]: 10.63.103.37 - - [06/Aug/2020:15:20:09 -0700] "POST /notifications/chat_user_is_typing/ HTTP/1.1" 200 2 "-" "RideHare/0.1 (com.ridehare.RideHare; build:4716; iOS 13.6.0) Alamofire/5.2.2"
2020-08-06T22:20:09.648912+00:00 heroku[router]: at=info method=POST path="/notifications/chat_user_is_typing/" host=ridehare.herokuapp.com request_id=c490aeda-1851-4f1e-b856-2c7309b51164 fwd="172.91.141.66" dyno=web.1 connect=2ms service=913ms status=200 bytes=218 protocol=https

如您所见,在此运行中,第一次ping时,我启动了一个计时器并将其存储在current_typists中。但是,当第二次ping进入时,根本没有计时器。 (第二个“ NO current timer”语句令人惊讶。) 根据我的阅读,Python中的类变量本质上是静态变量-每个类一个-但这表现为好像有多个。

这是否表明Django应用程序正在多个进程中运行?无论如何,我怎样才能最好地解决这个问题?

iCMS 回答:Python类变量在Django应用程序中表现异常

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/1790375.html

大家都在问