【问题标题】:Python code, should I thread? what to do?Python代码,我应该线程吗?该怎么办?
【发布时间】:2012-06-11 21:14:23
【问题描述】:

我有这段代码,它通过套接字侦听命令“更新的播放列表”。 当它得到这个命令时,它知道数据库中的播放列表已经更新,它连接到数据库并下载新的播放列表,然后开始播放这些文件。 我正在尝试找到解决此问题的最佳方法,因为当它获取命令,然后调用 Media_Player 函数时,它将播放播放列表中的所有视频,然后返回侦听套接字。

与此同时,如果已发送另一个“更新播放列表”命令,则此命令的发送者会收到错误消息,因为此代码不会监听。我希望媒体播放器不间断地播放,但它也必须不断收听,以防被告知已添加新的播放列表。

然后,如果添加了新的播放列表,它就会知道,当播放列表中的一个文件播放完毕时,它可以切换到新的播放列表并继续播放。

我不知道该怎么做,我以为我可以在一个进程中完成所有操作,然后为播放列表中的每个文件生成一个新线程,这样它就可以直接回到收听状态,但是那我怎么知道线程何时结束,因为播放列表中的每个文件的长度都不同。

还在函数listen_serv()中看到'return data'这一行,这是否意味着它不会因为返回而关闭连接?

# Echo server program
import socket
import time
import Database as DB

def listen_serv():
    HOST = ''                 # Symbolic name meaning all available interfaces
    PORT = 50007              # Arbitrary non-privileged port
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((HOST, PORT))
    s.listen(1)
    conn, addr = s.accept()
    print 'Connected by', addr
    while 1:
        data = conn.recv(1024)
        if not data: break
        conn.sendall('OK')
        return data

    conn.close()


while 1:
    val= listen_serv()
    if val=='Updated Playlist':
        PlayList = DB.get_play_list()
        Media_Player(PlayList)#This isnt implemented yet

【问题讨论】:

  • 您知道 Python 的全局解释器锁定问题吗?一次只运行一个线程。最好使用多处理库。

标签: python multithreading sockets


【解决方案1】:

您可以运行两个进程,一个是服务器,另一个是 MediaPlayer,中间有一个队列。

服务器将命令推送到 MediaPlayer 弹出它们的队列,播放每个视频后只需检查队列中是否有任何内容,如果有弹出并播放新的播放列表。

import socket
import time
import Database as DB
from multiprocessing import Process, Queue

def listen_serv(queue):
    HOST = ''                 # Symbolic name meaning all available interfaces
    PORT = 50007              # Arbitrary non-privileged port
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((HOST, PORT))
    s.listen(1)
    conn, addr = s.accept()
    print 'Connected by', addr
    while 1:
        data = conn.recv(1024)
        if not data:
            break
        conn.sendall('OK')
        queue.put(data)
    conn.close()

def media_player(queue):
    while 1:
        val = queue.get() # This will block until theres something on the queue.
        if val == 'Updated Playlist':
            PlayList = DB.get_play_list()
            Media_Player(PlayList, queue) # Media_Player needs to check the queue and update when appropriate.


if __name__ == '__main__':
    q = Queue()
    server = Process(target = listen_serv, args = (q,))
    media_player = Process(target = media_player, args = (q,))
    server.start()
    media_player.start()
    server.join()
    media_player.join()

你可以通过queue.empty()检查队列是否为空 我确信那里有更好的实现,如果有错误/问题我深表歉意。

祝你好运。

【讨论】:

  • 虽然我全心全意地支持基本的实施策略,但有几个问题需要解决。 listen_serv() 需要在 .accept() 调用周围增加一个额外的 while 语句。父进程需要捕获 KeyboardInterrupt 或有其他方式干净地离开。 Media_Player 几乎不需要访问队列;这就是调用函数的作用。
  • 我同意,我没有实现一个干净的方法来杀死每个进程,你可以简单地在队列中添加一个命令来告诉每个进程终止,比如“退出”,至于第二个问题,“当播放列表中的一个文件完成播放时,它可以切换到新的播放列表并继续播放”,因此 Media_player 需要监控队列以了解何时加载新的播放列表 ...
  • 所以我能做的是让媒体播放器在播放文件之间检查队列并进行相应更新。如果我将媒体播放器设置为检查数据库中的标志,甚至检查文件是否存在,这会不会有什么不同?
  • 我想我找到了一种更简单的使用线程的方法。如果我产生两个线程,一个是监听服务器,一个是媒体播放器。我使用 threading.Event()。这样,当监听服务器收到它的命令时,它就会设置事件。然后媒体播放器可以看到这一点,然后它可以从数据库中更新其播放列表。这是个好方法吗?
  • threading.Event() 非常原始,还请注意,python 中的线程并不是真正的多线程,因为 python 具有全局解释器锁wiki.python.org/moin/GlobalInterpreterLock,但多处理不是问题,但我怀疑你需要担心这一点,使用队列是最灵活的方式,因为它们的线程安全,您可以将多种类型推入并在检索值时阻塞,如果您想使用 threading.Event() ,它似乎有点受限。
猜你喜欢
  • 2021-10-01
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 2012-06-06
相关资源
最近更新 更多