How can I avoid to use global variables? (python - flask-socketio app)

我的未来我决定 提交于 2020-01-02 22:09:30

问题


I'm trying to figure out how to not use global variables for my application but I can't think of anything else.

I'm actually coding a web interface with the help of the Flask-SocketIO module to interact in real time with a music player.

This is a snippet of my code containing the play function (I think I only need one example and then I can adapt it for all the other functions):

from flask import Flask, render_template
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)
isPlaying = False #This is the variable that I would like to avoid making global

@socketio.on('request_play')
def cycle_play():
    global isPlaying
    if isPlaying == True:
        socketio.emit('pause', broadcast=True)
        isPlaying = False
    else:
        socketio.emit('play', broadcast=True)
        isPlaying = True

if __name__ == '__main__':
    socketio.run(app, port=5001)

This is only a stripped down version of the code but I think it's enough to understand what I'm trying to accomplish.

I need to access that variable also from other functions and I need to do the same with the song name, duration and current time.

Thanks in advance for the help and sorry if my English is not clear.


Here is the solution that I used:

from flask import Flask, render_template
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)

class Player():
    def __init__(self):
        self.isPlaying = False


    def cycle_play(self):
        if self.isPlaying == True:
            socketio.emit('pause', broadcast=True)
            self.isPlaying = False
        else:
            socketio.emit('play', broadcast=True)
            self.isPlaying = True


if __name__ == '__main__':
    player = Player()
    socketio.on('request_play')(player.cycle_play) #this is the decorator
    socketio.run(app, port=5001)

回答1:


The solution that suggests itself is to define a class which encapsulates both the state variable and the responses to its change. Since I'm not familiar with the details of Flask-SocketIO please treat this as pseduocode rather than something to be pasted in to a working program.

class PlayControl:
    def __init__(self, initial):
        self.is_playing = initial
    def cycle_play(self):
        if self.is_playing:
            socketio.emit('pause', broadcast=True)
            self.is_playing = False
    else:
            socketio.emit('play', broadcast=True)
            self.is_playing = True

You would then create an instance of this class, and pass the instance's cycle_play method to the same function you decorated your original function with. Because this behaviour is dynamic it's not appropriate to use a decorator on the method definition.

control = PlayControl(False)
socketio.on('request_play')(control.cycle_play)

To reduce the amount of program code you could even define a class that took the functions to call and the values to emit as arguments, generalising the concept further to make code more concise and with less boilerplate.




回答2:


You can use the user session to store such values. You can read up more about the session object here: flask.pocoo.org/docs/0.12/quickstart/#sessions.

from flask import session

@socketio.on('initialize')
def initialize(isPlaying):
    session['isPlaying'] = isPlaying

@socketio.on('request_play')
def cycle_play():
    # Note, it's good practice to use 'is' instead of '==' when comparing against builtin constants.
    # PEP8 recommended way is to check for trueness rather than the value True, so you'd want to first assert that this variable can only be Boolean.
    assert type(session['isPlaying']) is bool

    if session['isPlaying']: 
        socketio.emit('pause', broadcast=True)
        session['isPlaying'] = False
    else:
        socketio.emit('play', broadcast=True)
        session['isPlaying'] = True



回答3:


My advice would be use a class and inside init method just use self.isPlaying = False. You can always refer to this variable from all the function in the class. for exemple:

class PLAYER(object):   
   def __init__(self,other parameters):
    self.isPlaying = False
    #your cod
   def cycle_play(self):
        #global isPlaying
        if self.isPlaying == True:
           socketio.emit('pause', broadcast=True)
           self.isPlaying = False
        else:
           socketio.emit('play', broadcast=True)
           self.isPlaying = True


来源:https://stackoverflow.com/questions/46567275/how-can-i-avoid-to-use-global-variables-python-flask-socketio-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!