我正在将this bash script转换为Python。我现在有一个有效的Python版本。但是,为了让它工作,我不得不通过将它传递给一个长字符串来破解我传递给subprocess.Popen()的命令。 我不想使用一个长命令字符串。我希望将其分解为适当的个别参数。如何在特定的示例中执行此操作?
我的具体问题是如何更改此行:
process = subprocess.Popen(cmd, shell=True, ...
成这样的形式:
process = subprocess.Popen([prog, inf, arate, outf], shell=False, ...
这是我的完整代码,以便上述片段有意义:
#!/usr/bin/env python
import sys
import subprocess
import os.path
import argparse #requires Python 2.7 or above
parser = argparse.ArgumentParser(description='Converts (.M4V) videos into (.MP3) audio files using ffmpeg.')
parser.add_argument('-d','--directory', help='Source directory name',required=True)
parser.add_argument('-o','--output',help='Output directory name', required=False)
parser.add_argument('-a','--arate',help='ffmpeg\'s arate option', default="64K", required=False)
parser.add_argument('-s','--source',help='Input type; e.g., file ext (default .m4v)', default=".m4v", required=False)
parser.add_argument('-e','--ext',help='Output type; e.g., file ext (default .mp3)', default=".mp3", required=False)
parser.add_argument('-p','--program',help='application program e.g., /usr/bin/ffmpeg', default="/usr/bin/ffmpeg", required=False)
args = parser.parse_args()
arate = args.arate
source = args.source
new_ext = args.ext
prog = args.program
in_path = args.directory
if(not args.output):
out_path = in_path
else:
out_path = args.output
if(not os.path.isfile(prog)):
print("Command {} does not exist".format(prog))
else:
try:
filenames = os.listdir(in_path)
for file in filenames:
print("name={}\nextension={}".format(name, extension))
if(extension == source):
inf = os.path.join(in_path, file)
outf = os.path.join(out_path, name + new_ext)
cmd = "{xprog} -i '{xpath}' -b:a {art} -vn '{xout}'".format(xprog=prog, xpath=inf, art=arate, xout=outf)
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
stdout,stderr = process.communicate()
return_code = process.poll()
print("stdout='{}'\nstderr='{}'\nreturn_code='{}'".format(stdout, stderr, return_code))
except IOError as e:
print("Error: file not found.")
答案 0 :(得分:4)
如果在您的初始示例中传递的是“shell = True”,则the docs中的此注释是相关的:
shell参数(默认为False)指定是否使用shell作为 程序执行。如果shell为True,建议将args作为字符串而不是 作为一个序列
在哪种情况下:
subprocess.Popen(['ls -l'], shell=True)
结果:
total 1416
-rw-r--r-- 1 me AD\Domain Users 17 Nov 3 01:17 file1
drwxr-xr-x 7 me AD\Domain Users 238 Jan 22 15:34 dir
-rw-r--r-- 1 me AD\Domain Users 368 Nov 14 22:39 file2.xml
答案 1 :(得分:2)
如果我正确理解了您的问题,那么您希望将任意行从bash脚本转换为Popen
接受的格式。
Python文档有一个很好的(并且隐藏得很好)示例,说明如何执行此操作。 来自:http://docs.python.org/2/library/subprocess.html#popen-constructor
>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
现在我们可以在实践中应用以上信息:
import shlex
command = "/usr/bin/ffmpeg -i 'in_path/in_file.ext' -b:a arate -vn 'out_path/out_file.ext'"
print command
# /usr/bin/ffmpeg -i 'in_path/in_file.ext' -b:a arate -vn 'out_path/out_file.ext'
popen_cmd = shlex.split(command)
print popen_cmd
# ['/usr/bin/ffmpeg', '-i', 'in_path/in_file.ext', '-b:a', 'arate', '-vn', 'out_path/out_file.ext']
虽然使用os.system
答案 2 :(得分:0)
这是一个完整的工作解决方案,其中包含适当的Popen()参数。
import subprocess
import os.path
import argparse #requires Python 2.7 or above
parser = argparse.ArgumentParser(description='Converts (.M4V) videos into (.MP3) audio files using ffmpeg.')
parser.add_argument('-d','--directory', help='Source directory name',required=True)
parser.add_argument('-o','--output',help='Output directory name', required=False)
parser.add_argument('-a','--arate',help='ffmpeg\'s arate option', default="64K", required=False)
parser.add_argument('-s','--source',help='Input type; e.g., file ext (default .m4v)', default=".m4v", required=False)
parser.add_argument('-e','--ext',help='Output type; e.g., file ext (default .mp3)', default=".mp3", required=False)
parser.add_argument('-p','--program',help='application program e.g., /usr/bin/ffmpeg', default="/usr/bin/ffmpeg", required=False)
args = parser.parse_args()
arate = args.arate
source = args.source
new_ext = args.ext
prog = args.program
in_path = args.directory
if(not args.output):
out_path = in_path
else:
out_path = args.output
if(not os.path.isfile(prog)):
print("Command {} does not exist".format(prog))
else:
try:
filenames = os.listdir(in_path)
for file in filenames:
name, extension = os.path.splitext(file)
if(extension == source):
print("Processing: {}".format(file))
inf = os.path.join(in_path, file)
outf = os.path.join(out_path, name + new_ext)
process = subprocess.Popen([prog, "-i", inf, "-b:a", arate, "-vn", outf], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
stdout,stderr = process.communicate()
return_code = process.poll()
print("stdout='{}'\nstderr='{}'\nreturn_code='{}'".format(stdout, stderr, return_code))
else:
print("Skipping: {}".format(file))
except IOError as e:
print("Error: file not found.")
如果有人对此有所改进,请告诉我!