在 python 脚本中使用子进程将参数传递给 mpg123
Passing argument to mpg123 with subprocess in a python script
我有一个 Python3 脚本可以响应来自旋转拨号 phone 的输入(通过 raspberry pi 上的 GPIO 引脚。)如果我拨号 1
,我的脚本使用 subprocess
告诉 mpg123
播放名为 1.mp3
的文件。 2
播放 2.mp3
,以此类推,直到播放 7 次。这是有效的:
filename = "/media/"+str(number)+".mp3"
player = subprocess.Popen(["mpg123", filename, "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
如果我拨 8
,神奇的 8 球,脚本的行为应该不同。我希望它使用 "little shuffle" 标志 -z
调用 mpg123。从命令行,我知道如何进行调用:
mpg123 -z /media/mp3s/*
我想在我的 python3 脚本中使用这个确切的语法,但它不起作用。
if number ===8:
player = subprocess.Popen(["mpg123", "-z", "/media/mp3s/*"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
没有任何反应。脚本只是耐心等待下一个非 8 输入。
作为 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)
这会使脚本崩溃,因为 TypeError: Can't convert 'list' object to str implicitly
(尽管它确实在它消失之前成功地打印出了文件列表。)我想我必须非常接近至少一种方法,但我想不通最后一点语法。任何想法表示赞赏。**
好吧 - 我想出了一个方法让它工作,使用 mpg123 的内置目录指定标志,-B
。我仍然很好奇如何让我的其他一种或两种方法发挥作用。作为记录,这有效:
player = subprocess.Popen(["mpg123", "-Bz", "/media/mp3s/"],.......
要修复方法 A,您需要设置 shell=True
以获得通配符支持。命令本身应该是一个字符串而不是一个列表:
if number ===8:
player = subprocess.Popen("mpg123 -z /media/mp3s/*", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
文档在本节底部附近提到了此行为:
https://docs.python.org/3.6/library/subprocess.html#frequently-used-arguments
不同之处在于没有 shell 标志,python 是 运行 将列表中的第一个条目作为命令并将其余条目用作参数(*
从字面上看)。使用 shell 标志,整个字符串被放入,并且 shell 被允许做它想做的事。我无法重现这个确切的案例,但我想该命令会尝试 运行 并且找不到名为 /media/mp3s/*
.
的文件
不过我认为您的最终解决方案更 pythonic 但是您应该坚持下去。指定 shell=True
通常只意味着 python 完成文件名扩展等的内置函数未被使用(这些示例在上面列出的同一文档中列出)。
你的解决方案可能更好,但我想我会指出你的计划 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)
这里的问题是您将 filelist
作为一个项目传递给列表。所以你会得到一个包含列表的列表:
["mpg123", "-z", "--list", [ '/media/mp3s/1.mp3', '/media/mp3s/2.mp3' ]]
然而你想要的是这样的:
["mpg123", "-z", "--list", '/media/mp3s/1.mp3', '/media/mp3s/2.mp3']
要获得这些,您需要将列表一起加入:
player = subprocess.Popen(["mpg123", "-z", "--list"] + filelist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
未测试,但我相信这应该有效。
我有一个 Python3 脚本可以响应来自旋转拨号 phone 的输入(通过 raspberry pi 上的 GPIO 引脚。)如果我拨号 1
,我的脚本使用 subprocess
告诉 mpg123
播放名为 1.mp3
的文件。 2
播放 2.mp3
,以此类推,直到播放 7 次。这是有效的:
filename = "/media/"+str(number)+".mp3"
player = subprocess.Popen(["mpg123", filename, "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
如果我拨 8
,神奇的 8 球,脚本的行为应该不同。我希望它使用 "little shuffle" 标志 -z
调用 mpg123。从命令行,我知道如何进行调用:
mpg123 -z /media/mp3s/*
我想在我的 python3 脚本中使用这个确切的语法,但它不起作用。
if number ===8:
player = subprocess.Popen(["mpg123", "-z", "/media/mp3s/*"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
没有任何反应。脚本只是耐心等待下一个非 8 输入。
作为 B 计划,我想也许我可以使用 glob.glob
:
filelist = glob.glob('/media/mp3s/*.mp3')
print(filelist)
player = subprocess.Popen(["mpg123", "-z", "--list", filelist], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
这会使脚本崩溃,因为 TypeError: Can't convert 'list' object to str implicitly
(尽管它确实在它消失之前成功地打印出了文件列表。)我想我必须非常接近至少一种方法,但我想不通最后一点语法。任何想法表示赞赏。**
好吧 - 我想出了一个方法让它工作,使用 mpg123 的内置目录指定标志,-B
。我仍然很好奇如何让我的其他一种或两种方法发挥作用。作为记录,这有效:
player = subprocess.Popen(["mpg123", "-Bz", "/media/mp3s/"],.......
要修复方法 A,您需要设置 shell=True
以获得通配符支持。命令本身应该是一个字符串而不是一个列表:
if number ===8:
player = subprocess.Popen("mpg123 -z /media/mp3s/*", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
文档在本节底部附近提到了此行为:
https://docs.python.org/3.6/library/subprocess.html#frequently-used-arguments
不同之处在于没有 shell 标志,python 是 运行 将列表中的第一个条目作为命令并将其余条目用作参数(*
从字面上看)。使用 shell 标志,整个字符串被放入,并且 shell 被允许做它想做的事。我无法重现这个确切的案例,但我想该命令会尝试 运行 并且找不到名为 /media/mp3s/*
.
不过我认为您的最终解决方案更 pythonic 但是您应该坚持下去。指定 shell=True
通常只意味着 python 完成文件名扩展等的内置函数未被使用(这些示例在上面列出的同一文档中列出)。
你的解决方案可能更好,但我想我会指出你的计划 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)
这里的问题是您将 filelist
作为一个项目传递给列表。所以你会得到一个包含列表的列表:
["mpg123", "-z", "--list", [ '/media/mp3s/1.mp3', '/media/mp3s/2.mp3' ]]
然而你想要的是这样的:
["mpg123", "-z", "--list", '/media/mp3s/1.mp3', '/media/mp3s/2.mp3']
要获得这些,您需要将列表一起加入:
player = subprocess.Popen(["mpg123", "-z", "--list"] + filelist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
未测试,但我相信这应该有效。