Python:在从属模式下将命令发送到mplayer [英] Python: Send command to mplayer under slave mode

查看:148
本文介绍了Python:在从属模式下将命令发送到mplayer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在从属模式下运行时,我试图通过管道将命令发送到mplayer:

I'm trying to send command via pipe to mplayer when running it under slave mode like this:

import subprocess, time
# start mplayer
song = 'mysong.mp3'
cmd = ['mplayer', '-slave', '-quiet', song]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)

# send a command every 3 seconds.
# Full command reference here: http://www.mplayerhq.hu/DOCS/tech/slave.txt 
while True:
    print('sleep 3 seconds ...')
    time.sleep(3)
    cmd = 'get_meta_artist'
    print('send command: {}'.format(cmd))
    p.stdin.write(cmd)
    output = p.communicate()[0]
    print(output)

但是输出什么都没有.

我从在终端中运行相同的mplayer命令可以正常工作.我在这里想念什么?

Running the same mplayer command in the terminal works fine. What am I missing here?

更新:

我将cmd从"get_meta_artist"更改为"get_meta_artist \ n",以便将换行符也发送到管道,但输出中仍然没有任何内容.

I changed my cmd from "get_meta_artist" to "get_meta_artist\n" so that a line-break is sent to the pipe as well but still I got nothing in the output.

UPDATE2:

我将cmd更改为"\ npause \ n",并且音乐暂停了.因此,这意味着可以通过stdin发送命令.这意味着"\ nget_meta_artist \ n"命令的输出字符串未按预期方式传回....

I changed the cmd into "\npause\n" and the music was paused. So that means sending command via stdin worked. It means the output string of "\nget_meta_artist\n" command didn't get piped back as expected....

推荐答案

每个子进程只能使用一次.communicate().因此,不能在while循环中使用它.

You can only use .communicate() once per subprocess. So using it in a while loop doesn't work.

相反,您应该直接解析p.stdout的输出.如果有答案,每个答案似乎只有一行.

Instead, you should parse the output of p.stdout directly. There seems to be one line per answer if there is an answer.

为了防止阻塞,您有3个选择:

In order to prevent blocking, you have 3 options:

  1. 使用线程.您有一个单独的线程,该线程从p.stdout读取并将其数据发送到主线程.如果没有可用数据,它将阻止.

  1. Work with threads. You have a separate thread who reads from p.stdout and sends its data to the main thread. It blocks if no data is available.

p.stdout设置为非阻止模式.本质上,您必须执行以下操作:

Set p.stdout to non-blocking mode. Essentially, you'll have to do this:

import fcntl, os
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL,
    fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)

如果您随后在没有可用数据的情况下进行读取,则会得到一个异常(IOError: [Errno 11] Resource temporarily unavailable).

If you read then without data being available, you get an exception (IOError: [Errno 11] Resource temporarily unavailable).

使用select.select():仅当select.select([p.stdout], [], [], <timeout>)[0]是非空列表时才执行p.stdout.readline().在这种情况下,可以确保给定的文件对象具有可用数据,并且在读取时不会阻塞.

Work with select.select(): perform p.stdout.readline() only if select.select([p.stdout], [], [], <timeout>)[0] is a non-empty list. In that case, the given file object is guaranteed to have data available and to not block on reading.

为了将垃圾输出"与有用"输出分开,您可以执行以下操作:

In order to separate "garbage output" from "useful" output, you could do this:

def perform_command(p, cmd, expect):
    import select
    p.stdin.write(cmd + '\n') # there's no need for a \n at the beginning
    while select.select([p.stdout], [], [], 0.05)[0]: # give mplayer time to answer...
        output = p.stdout.readline()
        print("output: {}".format(output.rstrip()))
        split_output = output.split(expect + '=', 1)
        if len(split_output) == 2 and split_output[0] == '': # we have found it
            value = split_output[1]
            return value.rstrip()

然后做

print perform_command(p, 'get_meta_artist', 'ANS_META_ARTIST')
print perform_command(p, 'get_time_pos', 'ANS_TIME_POSITION')

这篇关于Python:在从属模式下将命令发送到mplayer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆