Python 对于循环,从外部函数触发下一个/上一个项

Python 对于循环,从外部函数触发下一个/上一个项,python,python-3.x,flask,Python,Python 3.x,Flask,我第一次接触到Python(Flask)。我正在尝试构建一个简单的API,它将充当具有播放/暂停/停止/上一个/下一个功能的远程播放列表。 我已经成功地构建了前两个特性(Play/Stop),无论何时我都需要一些关于(Prev/Next)的想法。请记住,在每次迭代结束时,我都有一个睡眠事件。我使用多线程(由Flask自动启用)在运行play()时调用stop() playing = 0 @app.route('/play', methods=['POST']) def play():

我第一次接触到Python(Flask)。我正在尝试构建一个简单的API,它将充当具有播放/暂停/停止/上一个/下一个功能的远程播放列表。

我已经成功地构建了前两个特性(Play/Stop),无论何时我都需要一些关于(Prev/Next)的想法。请记住,在每次迭代结束时,我都有一个睡眠事件。我使用多线程(由Flask自动启用)在运行play()时调用stop()

playing = 0


@app.route('/play', methods=['POST'])
def play():
    mediaFiles = request.json
    global playing
    playing = 1
    while playing == 1:
        for file in mediaFiles['mediaFiles']:
            if playing == 0:
                break
            print(file['path'])
            time.sleep(5)
    return 'Played'


@app.route('/stop')
def stop():
    global playing
    playing = 0
    return 'Stopped...'
我尝试创建全局“currentIndex”变量,该变量将跟踪数组中最后播放的索引,然后使用旋转数组并从暂停的位置开始。这可能行得通,但我仍然保留了上一个/下一个功能


我相信有一种比使用while和for更好的方法来处理这个问题,因为从我看来,甚至不可能使用这种方法并具有(Prev/Next)特性

只需保留文件的当前索引即可。但这只是一个暗示,但可能或多或少:

playing = 0

current_index = 0


@app.route('/play', methods=['POST'])
def play():
    mediaFiles = request.json
    global playing
    playing = 1
    while playing == 1:
        for current_index, file in enumerate(mediaFiles['mediaFiles'][current_index:], current_index):
            if playing == 0:
                break
            print(file['path'])
            time.sleep(5)
        current_index = 0            # loop back to 0 after last file
    return 'Played'
上一个/下一个功能只需增加/减少当前索引即可。困难的部分是,如果您试图从不同的线程更新当前的_索引,您必须构建一个同步迭代器来防止竞争条件

例如,您可以使用:

class syncenumerate:
    def __init__(self, lock, iterable, start=0):
        self.lock = lock
        self.iter = enumerate(iterable, start)
    def __iter__(self):
        return self
    def __next__(self):
        self.lock.acquire()
        try:
            ret = next(self.iter)
        finally:
            self.lock.release()    # ensure that the lock is released at StopIteration
        return ret
您可以轻松实现线程安全同步:

playing=0
lck = threading.Lock()
current_changed = 0
...
    while playing == 1:
        for current_index, file in syncenumerate(lck, mediaFiles['mediaFiles']
                [current_index:], current_index):
            if current_changed = 1:    # restart enumeration is current was changed
                lck.acquire()
                current_changed = 0
                lck.release()
                break
            if playing == 0:
                ...
并在下一步中进行更改:

lck.acquire()
current_index += 1
if current_index >= max: current_index = 0
current_changed = 1
lck.release()

我最终使用了threading.Condition()及其wait()和notify()函数。这样,对于下一步,我只需调用notify(),对于上一步,我使用了当前的索引跟踪器。没有使用syncenumerate。谢谢你!