在python中的子进程中发送命令

时间:2012-12-13 20:45:57

标签: python subprocess

我只想在我的树莓派上建立一个小蟒蛇音乐客户端。我安装了“mpg321”,它运行良好,但现在我的问题。发送命令后

os.system("mpg321 -R testPlayer")

python等待播放,暂停或退出等用户输入。如果我在终端中写这个,播放器暂停音乐或退出。完美,但我希望python这样做,所以我发送命令

os.system("LOAD test.mp3")

其中LOAD是加载此mp3的命令。但没有任何反应。当我通过终端退出播放器时,我收到错误:

sh: 1: LOAD: not found

我认为这意味着

os.system("mpg321 -R testPlayer")

占用整个过程,在我退出之后,python尝试执行comman LOAD。那么如何让这些东西一起工作呢?

我的代码:

import os

class PyMusic:
    def __init__(self):
        print "initial stuff later"

    def playFile(self, fileName, directory = ""):
        os.system("mpg321 -R testPlayer")
        os.system("LOAD test.mp3")


if __name__ == "__main__":
    pymusic = PyMusic()
    pymusic.playFile("test.mp3")

感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

首先,您几乎不应该使用os.system。请参阅subprocess模块。

使用subprocess的一个主要优点是你可以选择你想要的任何行为 - 在后台运行它,启动它并等待它完成(如果它返回非零则抛出异常),无论什么都有意义,明确地与其stdinstdout互动。

在这里,您不是要尝试运行另一个命令"LOAD test.mp3",而是尝试将其作为输入传递给现有进程。所以:

p = subprocess.Popen(['mpg321', '-R', 'testPlayer'], stdin=PIPE)

然后你可以这样做:

p.stdin.write('LOAD test.mp3\n')

这大致等同于从shell执行此操作:

echo -e 'LOAD test.mp3\n' | mpg321 -R testPlayer

但是,您应该阅读communicate,因为只要有可能弄清楚如何使代码与communicate一起使用,它就比尝试处理通用I / O简单得多(特别是如果你以前从未用管道,插座等编码过。)

或者,如果您尝试与命令行UI进行交互(例如,在得到正确的提示之前无法发送命令),您可能需要查看“expect”库。其中有一些可供选择,因此您应该search at PyPI为您找到合适的一个(虽然我可以说我过去已成功使用pexpect,并且文档已满比大多数expect文档更快地获得想法的样本。

答案 1 :(得分:2)

您正在寻找一种向stdin发送数据的方法。这是example of this使用Popen:

from subprocess import Popen, PIPE, STDOUT

p = Popen(['mpg321', '-R testPlayer'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)

mpg123_stdout = p.communicate(input='LOAD test.mp3\n')[0]
print(mpg123_stdout)

您建立了指向stdinstdout的指针,然后在您开始流程后,您与stdin进行通信,并从stdout读取。一定要发送新行(回车)