写命令在Windows

问题描述:

与Python 3 mplayer的子我有一个非常...特定问题。真的试图找到一个更广泛的问题,但不能。写命令在Windows

我想使用的mplayer作为子进程来播放音乐(在Windows和Linux的也),并保留命令传递给它的能力。我已经在python 2.7中用subprocess.Popenp.stdin.write('pause\n')完成了。

但是,这似乎没有幸存下来的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') 

看到,因为这个代码工作(不b收费)2.7,我只能假设编码字符串作为bytes以某种方式修改字节的值,使得MPlayer能不再理解了吗?然而,当我试图看到通过管道发送什么字节它看起来是正确的。它也可能是窗口管道奇怪。我已经用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') 

看到,因为这个代码在2.7的工作(不b S),我只能假设编码字符串作为字节以某种方式更改字节值,以便mplayer无法再理解它?

'pause\n'在Python 2 正是相同的值b'pause\n' - 而且你可以使用b'pause\n'关于Python 2太(通信代码的意图)。

区别在于Python 2上的bufsize=0因此.write()会立即将内容推送到子进程,而Python 3上的.write()则将其放入某个内部缓冲区中。添加.flush()调用,清空缓冲区。

通行证universal_newlines=True,以便在Python 3的文本模式(那么你可以使用'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。要放弃输出,请改为使用stdout=subprocess.DEVNULL。见How to hide output of subprocess in Python 2.7

+0

谢谢!我不久将检查该解决方案......是的,我故意没有使用universal_newlines,因为它会改变我的字符串的值,但我想我甚至没有想到的是mplayer的Windows版本可以期待一个\ r \ n,在事实上它可能是。是的,我一直在我的实际代码中使用DEVNULL,不过谢谢你的提示。 – Nacht

+0

换行似乎不重要,但冲洗流的作品!非常感谢...感叹我可能应该认为这是诚实的。哦,谢谢 – Nacht