如何避免使用全局变量?(python-flask socketio应用程序)
我试图找出如何在我的应用程序中不使用全局变量,但我想不出其他任何东西 我实际上是在Flask SocketIO模块的帮助下编写一个web界面,以便与音乐播放器实时交互 这是包含play函数的代码片段(我想我只需要一个示例,然后我就可以将其用于所有其他函数): 这只是一个精简版本的代码,但我认为它足以理解我试图实现的目标 我还需要从其他函数访问该变量,我需要对歌曲名称、持续时间和当前时间执行相同的操作 提前感谢您的帮助,如果我的英语不清楚,请原谅如何避免使用全局变量?(python-flask socketio应用程序),python,global-variables,flask-socketio,Python,Global Variables,Flask Socketio,我试图找出如何在我的应用程序中不使用全局变量,但我想不出其他任何东西 我实际上是在Flask SocketIO模块的帮助下编写一个web界面,以便与音乐播放器实时交互 这是包含play函数的代码片段(我想我只需要一个示例,然后我就可以将其用于所有其他函数): 这只是一个精简版本的代码,但我认为它足以理解我试图实现的目标 我还需要从其他函数访问该变量,我需要对歌曲名称、持续时间和当前时间执行相同的操作 提前感谢您的帮助,如果我的英语不清楚,请原谅 以下是我使用的解决方案: from flask
以下是我使用的解决方案:
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)
建议自己的解决方案是定义一个类,该类封装状态变量和对其更改的响应。由于我不熟悉Flask SocketIO的详细信息,请将其视为psedoocode,而不是要粘贴到工作程序中的内容
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
然后,您将创建该类的一个实例,并将该实例的cycle\u play
方法传递给您装饰原始函数的同一个函数。因为这种行为是动态的,所以不适合在方法定义上使用decorator
control = PlayControl(False)
socketio.on('request_play')(control.cycle_play)
为了减少程序代码的数量,您甚至可以定义一个类,将要调用的函数和要发出的值作为参数,进一步概括这个概念,使代码更简洁,使用更少的样板文件。我的建议是使用一个类,在init方法中只使用self.isplay=False。您始终可以从类中的所有函数中引用此变量。 例如:
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
您可以使用用户会话来存储这些值。您可以在此处阅读有关会话对象的更多信息: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
您对全局变量的关注点是什么?如果必须从其他函数访问变量,那么它必须位于主环境中。如果不希望函数直接与之交互,可以将“def cycle_play(copy_of_global_variable)”放在函数的开头,将“return(copy_of_global_variable)”放在函数的结尾,然后必须记住使用“global_variable=cycle_play(global_variable)”调用函数.@F.Rossi我没有使用Flask+socketio的经验,但在web应用程序中使用进程全局状态通常是一个很大的禁忌。要么是每个用户的状态,您希望通过会话对其进行管理,要么是“共享”状态,您希望通过一些数据库(关系型或非关系型)对其进行管理。感谢您提供有关使用“is”的信息,然而,也许我遗漏了一些东西,但会话是某个东西的标准名称吗?因为我得到了这个错误:NameError:name'session'没有定义“#注意,在与内置常量进行比较时,最好使用'is'而不是'==''”=>Nope,在这种情况下最好的做法是不与任何东西进行比较,所有python对象在布尔上下文中使用时都有一个真值,所以
如果有什么:dou this()
是这里的好做法。当您想要比较对象标识(两个名称都指向同一个对象)时,您只能使用is
。也就是说,如果必须维护的状态是“每用户”状态,那么使用会话确实非常有意义@F.Rossi您需要导入会话
才能使用它:如果某件事是真的
和如果某件事==True
一样糟糕,这是一个常见的错误。如果有什么东西,只需使用。如果您确实需要一个布尔值,您可以始终使用bool(something)
。[从肥皂盒中下来]。添加缺少的导入可能会有帮助。我对此进行了改进,因为它使用了知识,我不必提供比我可能仓促接受的答案更好的解决方案。如果提问者读到:您可能会重新考虑您的选择(我相信您可以更改您接受的答案0。我没有使用Flask+socketio的经验,但我怀疑在任何web应用程序中使用流程全局状态(上例中的控件
对象仍然是全局的)。正确。但您可以(例如)有一个控件列表,或者一个你可以按名称查找的控件字典。但是,你已经知道了。也许我对OP的具体需求的回答过于狭隘。如果我没有犯错误的格式错误(现已修复),这可能会有所帮助。“也许我对OP的具体需求的回答过于严格。”:是的,我的拙见…当你有多个单一进程为应用服务时,即使是列表或目录等也会崩溃(多进程设置是标准)。这就是为什么我们使用数据库(任何类型)用于状态持久性和进程间共享。谢谢。我读得不够仔细,应该已经回答了关于会话状态的问题。对于任何Python主题,您都不必谦虚。这很好,但您仍然需要安排所需的事件来在该类的特定实例上调用该方法。
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