简体   繁体   English

在python脚本中通过子进程将参数传递给mpg123

[英]Passing argument to mpg123 with subprocess in a python script

I have a Python3 script that responds to input from a rotary dial phone (via GPIO pins on a raspberry pi.) If I dial a 1 , my script uses subprocess to tell mpg123 to play a file called 1.mp3 . 我有一个Python3脚本,该脚本可响应来自旋转拨号电话的输入(通过树莓派上的GPIO引脚)。如果我拨打1 ,则脚本使用subprocess告诉mpg123播放名为1.mp3的文件。 2 plays 2.mp3 , and so on up to 7. This is working: 2播放2.mp3 ,依此类推,直到7。

filename = "/media/"+str(number)+".mp3"
player = subprocess.Popen(["mpg123",  filename, "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

If I dial 8 , the magic 8-ball, the script should behave differently. 如果我拨8魔术球,则脚本的行为应有所不同。 I want it to call mpg123 with the "little shuffle" flag, -z . 我希望它使用“ little shuffle”标志-z来调用mpg123。 From the command line, I know how to make that call: 从命令行,我知道如何进行该调用:

 mpg123 -z /media/mp3s/*

I want to use this exact syntax in my python3 script, but it isn't working. 我想在我的python3脚本中使用这个确切的语法,但是它不起作用。

 if number ===8:
         player = subprocess.Popen(["mpg123", "-z", "/media/mp3s/*"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Nothing happens. 什么都没发生。 Script just waits patiently for the next non-8 input. 脚本只是耐心地等待下一个非8输入。

As a Plan B, I thought maybe I could pass a list of files to mpg123 with glob.glob : 作为计划B,我想也许可以通过glob.glob将文件列表传递给mpg123:

filelist = glob.glob('/media/mp3s/*.mp3')
print(filelist)
player = subprocess.Popen(["mpg123", "-z", "--list", filelist], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

This crashes the script because TypeError: Can't convert 'list' object to str implicitly (Though it does successfully print out the list of files before it dies.) I think I must be very close with at least one approach, but I can't figure out the last little bit of syntax. 这会导致脚本崩溃,因为TypeError: Can't convert 'list' object to str implicitly (尽管它确实在死之前成功打印出了文件列表。)我想我至少必须非常接近一种方法,但是我可以没有弄清楚语法的最后一点。 Any ideas appreciated.** 任何想法表示赞赏。**


Alright - I figured out a way to make it work, using mpg123's builtin directory specifying flag, -B . 好的-我想出了一种方法,可以使用mpg123的内置目录指定标志-B I am still curious about how to get one or both of my other approaches to work. 我仍然对如何使一种或两种其他方法起作用感到好奇。 For the record, this works: 作为记录,这有效:

player = subprocess.Popen(["mpg123", "-Bz", "/media/mp3s/"],.......

To fix approach A, you'll need to set shell=True to get wildcard support. 要解决方法A,您需要设置shell=True以获得通配符支持。 The command itself should then be a string instead of a list however: 然后,命令本身应为字符串而不是列表:

if number ===8:
     player = subprocess.Popen("mpg123 -z /media/mp3s/*", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

The docs mention this behavior near the bottom of this section: 文档在本节底部附近提到了此行为:

https://docs.python.org/3.6/library/subprocess.html#frequently-used-arguments https://docs.python.org/3.6/library/subprocess.html#frequently-used-arguments

The difference is that without the shell flag, python is running the first entry in the list as the command and using the rest as arguments (the * taken literally). 不同之处在于,没有shell标志,python会将列表中的第一个条目作为命令运行,并将其余的作为参数运行(字面上的* )。 With the shell flag, the entire string is plopped in and the shell is allowed to do what it will. 使用shell标志,可以将整个字符串放入其中,并允许shell执行将要执行的操作。 I can't reproduce this exact case but I imagine the command tries to run and fails to find a file called /media/mp3s/* . 我无法重现这种确切的情况,但我想命令会尝试运行,但找不到名为/media/mp3s/*

I would argue however that your final solution is more pythonic however and you should stick with that. 但是,我认为您的最终解决方案更适合pythonic,因此您应该坚持这一点。 Specifying shell=True generally just means that the python built-ins that accomplish filename expansion, etc. aren't being utilized (examples of these listed in the same doc listed above). 指定shell=True通常仅表示未使用完成文件名扩展等功能的python内置程序(这些示例在上面列出的同一文档中列出)。

Your solution is probably better, however I thought I would point out the problem with your plan B: 您的解决方案可能更好,但是我想指出您的计划B的问题:

filelist = glob.glob('/media/mp3s/*.mp3')
print(filelist)
player = subprocess.Popen(["mpg123", "-z", "--list", filelist], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

The problem here is you are passing filelist as an item to the list. 这里的问题是您要将filelist作为项目传递给列表。 So you would get a list containing a list: 因此,您将获得一个包含列表的列表:

["mpg123", "-z", "--list", [ '/media/mp3s/1.mp3', '/media/mp3s/2.mp3' ]]

However what you wanted is this: 但是,您想要的是:

["mpg123", "-z", "--list", '/media/mp3s/1.mp3', '/media/mp3s/2.mp3']

To get these you need to join the lists together: 要获得这些,您需要将列表一起加入:

player = subprocess.Popen(["mpg123", "-z", "--list"] + filelist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Not tested, but I believe this should work. 未经测试,但我相信这应该可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM