我正在尝试使用子进程执行脚本,当我手动执行它时,我知道它可以工作;以下内容来自我的调用脚本:
# the command string we want to issue to ffmpeg.py to generate our ffmpeg command strings
commandString = [
'python',
os.path.join(SCRIPT_DIR, 'ffmpeg.py'),
'-i', os.path.join('/srv/nfsshare/transcode50', userFolder, directory, title),
'-d', os.path.join('/srv/nfsshare/transcode50', userFolder, directory),
'-r', request.POST['framerate'],
'-p 2', '-f', ",".join(formats), '-t', ",".join(rasters)
]
# call transcode50 script to generate condor_execute.py
subprocess.call(' '.join(commandString) + ' > /srv/nfsshare/transcode50/output.txt', shell=True)
实际的脚本本身将生成一个命令字符串列表并将它们输出到控制台。我将输出传送到一个名为output.txt的文件,在该命令字符串的末尾进行测试,因为我正在运行Django的Python代码并且无法实时看到shell输出,但当我检查每个文件时时间,没有任何东西,并且调用脚本也有(产生Python文件)的副作用不会发生。因此,我相信我可能会或可能不会考虑使用子进程模块,也许它是特定于Django的?
答案 0 :(得分:1)
使用'.join(...)将列表转换为shell字符串是有风险的,因为列表中可能存在需要shell转义的内容(如文件名中的空格)。你最好坚持使用命令列表而不是shell。你还应该捕获stderr,这是好东西的所在。最后使用check_call并将整个事件包装在记录执行失败的异常处理程序中。
try:
commandString = [
'python',
os.path.join(SCRIPT_DIR, 'ffmpeg.py'),
'-i', os.path.join('/srv/nfsshare/transcode50', userFolder, directory, title),
'-d', os.path.join('/srv/nfsshare/transcode50', userFolder, directory),
'-r', request.POST['framerate'],
'-p 2', '-f', ",".join(formats), '-t', ",".join(rasters)
]
# call transcode50 script to generate condor_execute.py
subprocess.check_call(commandString,
stdout=open('/srv/nfsshare/transcode50/output.txt', 'w'),
stderr=subprocess.STDOUT)
except Exception, e:
# you can do fancier logging, but this is quick
open('/tmp/test_exception.txt', 'w').write(str(e))
raise