使用 python 3 in windows 将命令写入 mplayer 子进程
writing commands to mplayer subprocess with python 3 in windows
我有一个...非常具体的问题。真的试图找到更广泛的问题,但找不到。
我正在尝试使用 mplayer 作为子进程来播放音乐(在 windows 和 linux 上),并保留向其传递命令的能力。我在 python 2.7 中用 subprocess.Popen
和 p.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')
鉴于此代码在 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')
seeing as this code worked (without the b
s) in 2.7, i can only assume encoding the string as a bytes is somehow changing the byte values so that mplayer can't understand it any more?
'pause\n'
在 Python 2 中 完全 与 b'pause\n'
相同的值 - 此外,您可以使用 b'pause\n'
Python 2 也是(传达代码的意图)。
区别在于 bufsize=0
on Python 2 因此 .write()
立即将内容推送到子进程,而 .write()
on Python 3 将其放入在一些内部缓冲区中。添加 .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
我有一个...非常具体的问题。真的试图找到更广泛的问题,但找不到。
我正在尝试使用 mplayer 作为子进程来播放音乐(在 windows 和 linux 上),并保留向其传递命令的能力。我在 python 2.7 中用 subprocess.Popen
和 p.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')
鉴于此代码在 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')
seeing as this code worked (without the
b
s) in 2.7, i can only assume encoding the string as a bytes is somehow changing the byte values so that mplayer can't understand it any more?
'pause\n'
在 Python 2 中 完全 与 b'pause\n'
相同的值 - 此外,您可以使用 b'pause\n'
Python 2 也是(传达代码的意图)。
区别在于 bufsize=0
on Python 2 因此 .write()
立即将内容推送到子进程,而 .write()
on Python 3 将其放入在一些内部缓冲区中。添加 .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