2016-02-26 64 views
0

與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

看到,因爲這個代碼在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