代码之家  ›  专栏  ›  技术社区  ›  Nacht

在windows中使用python3向mplayer子进程写入命令

  •  0
  • Nacht  · 技术社区  · 8 年前

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

    我正在尝试将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')
    

    查看此代码的工作情况(没有 b s) 在2.7中,我只能假设将字符串编码为 字节 是否以某种方式更改了字节值,使mplayer无法再理解它?然而,当我试图确切地看到通过管道发送的字节时,它看起来是正确的。这也可能是windows管道的行为很奇怪。我已经用两个cmd试过了。exe和powershell,因为我知道powershel将管道解释为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 回复  |  直到 7 年前
        1
  •  2
  •   Community kgiannakakis    7 年前

    查看此代码的工作情况(没有 b s) 在2.7中,我只能假设将字符串编码为字节是在某种程度上改变字节值,这样mplayer就无法理解它了?

    'pause\n' 在Python 2中是 确切地 与相同的值 b'pause\n' --此外,您可以使用 b'暂停\n' 在Python 2上(以传达代码的意图)。

    不同的是 bufsize=0 在Python 2上,因此 .write() 将内容立即推送到子流程 .写入() 在Python 3上,将其放在一些内部缓冲区中。添加 .flush() 调用,以清空缓冲区。

    通过 universal_newlines=True ,以在Python 3上启用文本模式(然后可以使用 '暂停\n' 而不是 b'暂停\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

    推荐文章