Python:在从属模式下将命令发送到mplayer [英] Python: Send command to mplayer under slave mode
问题描述
在从属模式下运行时,我试图通过管道将命令发送到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:
-
使用线程.您有一个单独的线程,该线程从
p.stdout
读取并将其数据发送到主线程.如果没有可用数据,它将阻止.
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屋!