2010-10-14 3 views
4

Я пишу простой интерфейс на Python, чтобы играть и записывать интернет-радиоканалы (например, от shoutcast), используя mplayer (в подпроцессе). Когда пользователь нажимает на станцию, запускается следующий код:Python: заголовок заголовка парсера с mplayer

 

url = http://77.111.88.131:8010 # only an example 
cmd = "mplayer %s" % url 
p = subprocess.Popen(cmd.split(), shell=False) 
wait = os.waitpid(p.pid, 1) 
return int(p.pid) 
 

Это прекрасно работает, поток начинает играть так, как должен. Хотя я хотел бы как-то разобрать название потока. Кажется, мне нужно получить название из выхода mplayer. Это вывод, когда я воспроизвожу поток в терминале:

 
$ mplayer http://77.111.88.131:8010 
MPlayer 1.0rc4-4.4.5 (C) 2000-2010 MPlayer Team 
mplayer: could not connect to socket 
mplayer: No such file or directory 
Failed to open LIRC support. You will not be able to use your remote control. 

Playing http://77.111.88.131:8010. 
Resolving 77.111.88.131 for AF_INET6... 
Couldn't resolve name for AF_INET6: 77.111.88.131 
Connecting to server 77.111.88.131[77.111.88.131]: 8010... 
Name : Justmusic.Fm 
Genre : House 
Website: http://www.justmusic.fm 
Public : yes 
Bitrate: 192kbit/s 
Cache size set to 320 KBytes 
Cache fill: 0.00% (0 bytes) 
ICY Info: StreamTitle='(JustMusic.FM) Basement - Zajac, Migren live at Justmusic 2010-10-09';StreamUrl='http://www.justmusic.fm'; 
Cache fill: 17.50% (57344 bytes) 
Audio only file format detected. 

Он затем бежит, пока не остановится. Итак, вопрос в том, как я могу получить «(JustMusic.FM) Подвал - Заяк, Мигрен живут в Justmusic 2010-10-09» и все еще позволяют запустить процесс? Я не думаю, что subprocess() фактически сохраняет вывод, но я могу ошибаться. Любая помощь глубоко признателен :)

ответ

5

stdout Установите аргумент PIPE, и вы будете иметь возможность слушать вывод команды:

p= subprocess.Popen(['mplayer', url], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
for line in p.stdout: 
    if line.startswith('ICY Info:'): 
     info = line.split(':', 1)[1].strip() 
     attrs = dict(re.findall("(\w+)='([^']*)'", info)) 
     print 'Stream title: '+attrs.get('StreamTitle', '(none)') 
+0

Большое спасибо! Хотя stdout = PIPE, stderr = STDOUT полностью блокирует TK GUI. Если «разбить» цикл, то mplayer остановится примерно через 30 секунд. Как это обойти? Может быть, избежать цикла, не влияя на процесс? – frigg

+0

Попробуйте сначала с 'p.communicate()'. Похоже, что буфер заполняется и не читается вовремя по какой-то причине, заставляя дочерний процесс блокироваться. Вам может не понадобиться 'stdout' * и *' stderr'; по-видимому, сообщение, которое вы хотите, выходит только на одном из них, я просто не знаю, что! Может быть, stderr, и в этом случае попробуйте просто 'stderr = PIPE'? – bobince

1
import re 
import shlex 
from subprocess import PIPE, Popen 

URL = 'http://relay2.slayradio.org:8000/' 

def get_exitcode_stdout_stderr(cmd): 
    """ 
    Execute the external command and get its exitcode, stdout and stderr. 
    """ 
    args = shlex.split(cmd) 

    proc = Popen(args, stdout=PIPE, stderr=PIPE) 
    out, err = proc.communicate() 
    exitcode = proc.returncode 
    # 
    return exitcode, out, err 

def get_title(): 
    cmd = "mplayer -endpos 1 -ao null {url}".format(url=URL) 
    out = get_exitcode_stdout_stderr(cmd)[1] 

    for line in out.split("\n"): 
#  print(line) 
     if line.startswith('ICY Info:'): 
      match = re.search(r"StreamTitle='(.*)';StreamUrl=", line) 
      title = match.group(1) 
      return title 

def main(): 
    print(get_title()) 

Edit: я имел другое (более простое) решение, которое перестало работать, поэтому я обновил свое решение. Идея: mplayer останавливается через 1 сек. (-endpos 1).