2012-12-13 40 views
0

我只想在我的树莓派上构建一个小型的python音乐客户端。我安装了“mpg321”,它工作的很好,但现在我的问题。发送命令后在python中发送关于子进程的命令

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尝试执行LOAD comman。那么我怎么才能让这些东西一起工作呢?

我的代码:

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") 

感谢您的帮助!

回答

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要简单得多(尤其是如果你从未编码过与之前的管道,插座等)。或者,如果您尝试与命令行界面进行交互(例如,只有在获得正确的提示后才能发送命令),则可能需要查看“期望”库。有一些可供选择的,所以你应该search at PyPI为你找到合适的人(尽管我可以说我过去成功地使用了pexpect,并且文档中充满了能够将想法传达给文档比大多数expect文档要快得多)。

+0

+1完整性:) –

+0

谢谢你的完美!也感谢您的提示和信息! – emha

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读取。请务必发送新行(回车)

+0

+1为简洁起见。我不确定这会起作用,因为我认为他需要等待'mpg321'的提示 - 但如果确实如此,这是迄今为止最简单,最清洁的解决方案。 – abarnert