在Windows中使用python 3向mplayer子进程写入命令

时间:2016-02-26 02:29:53

标签: python subprocess cross-platform mplayer

我有......非常具体的问题。真的试图找到一个更广泛的问题,但不能。

我正在尝试使用mplayer作为播放音乐的子进程(在Windows和Linux上),并保留向其传递命令的能力。我已经使用subprocess.Popenp.stdin.write('pause\n')在python 2.7中完成了这个。

然而,这似乎没有幸免于Python 3之旅。我必须使用'pause\n'.encode()b'pause\n'转换为bytes,并且mplayer进程不会暂停。但是,如果我使用p.communicate,它似乎确实有用,但由于this question声称它只能在每个进程中调用一次,因此我已将此作为可能性。

这是我的代码:

p = subprocess.Popen('mplayer -slave -quiet "C:\\users\\me\\music\\Nickel Creek\\Nickel Creek\\07 Sweet Afton.mp3"', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
time.sleep(1)
mplayer.stdin.write(b'pause\n')
time.sleep(1)
mplayer.stdin.write(b'pause\n')
time.sleep(1)
mplayer.stdin.write(b'quit\n')

看到这段代码在2.7中工作(没有b s),我只能假设编码字符串为bytes以某种方式改变字节值,以便mplayer无法理解它更多?但是,当我试图确切地看到通过管道发送的字节时,它看起来是正确的。它也可能是Windows管道行为奇怪。我用cmd.exe和powershell试过这个,因为我知道powershell将管道解释为xml。我使用此代码来测试管道中的内容:

# test.py
if __name__ == "__main__":
    x = ''
    with open('test.out','w') as f:
        while (len(x) == 0 or x[-1] != 'q'):
            x += sys.stdin.read(1)
            print(x)
        f.write(x)

p = subprocess.Popen('python test.py', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
p.stdin.write(b'hello there\ntest2\nq\n')

1 个答案:

答案 0 :(得分:2)

  

看到这段代码在2.7中工作(没有b s),我只能假设编码字符串,因为字节以某种方式改变字节值,以便mplayer不能再理解它了?

Python 2中的

'pause\n' 与<{1}}完全相同 - 此外,您也可以在Python 2上使用b'pause\n'(以传达意图代码)。

不同之处在于Python 2上的b'pause\n'因此bufsize=0会立即将内容推送到子流程,而Python 3上的.write()会将其放入某个内部缓冲区。添加.write()调用,清空缓冲区。

传递.flush(),在Python 3上启用文本模式(然后您可以使用universal_newlines=True代替'pause\n')。如果b'pause\n'期望mplayer而不是os.newline作为行尾,则可能还需要它。

b'\n'

不相关:除非您从管道中读取,否则不要使用#!/usr/bin/env python3 import time from subprocess import Popen, PIPE LINE_BUFFERED = 1 filename = r"C:\Users\me\...Afton.mp3" with Popen('mplayer -slave -quiet'.split() + [filename], stdin=PIPE, universal_newlines=True, bufsize=LINE_BUFFERED) as process: send_command = lambda command: print(command, flush=True, file=process.stdin) time.sleep(1) for _ in range(2): send_command('pause') time.sleep(1) send_command('quit') ,否则您可能会挂起子进程。要丢弃输出,请改用stdout=PIPE。见How to hide output of subprocess in Python 2.7