如何在Python CGI脚本中捕获子进程错误?

3 投票
3 回答
4694 浏览
提问于 2025-04-16 15:40

我正在尝试写一个Python的CGI脚本,目的是通过subprocess来调用sox(一个音频处理程序)。问题是,当我从sox调用中遇到错误时,整个程序就崩溃了,并且我在Apache中收到了“头部格式错误”的提示。

相关的代码部分:

def downsample(in_file, in_location, sox, out_location):
  """ run sox """
...
  sox = shlex.split(sox)
  retcode = subprocess.check_call(sox)
  if not retcode == 0:
    print '<b>something went wrong in sox: returned error code ' +\
          retcode + ', but we are continuing anyway...</b>'
  """p = subprocess.Popen(sox)
  if p.stdout:
    print '<b>something happened in sox: returned ' +\
          p.stdout.read() + ', but we will keep going...</b>'
  if p.stderr:
    print '<b>something happened in sox: returned ' +\
          p.stderr.read() + ', but we will keep going...</b>'"""
...

def main():
  print "Content-Type: text/html\n\n"

...
    downsample(in_file, in_location, command, out_location)
...

if __name__ == '__main__':
  main()

我现在使用check_call来让CGI的错误处理程序打印出错误堆栈(这样可以避免出现500错误页面),但我其实想自己捕获这个错误,处理完后继续执行脚本。我尝试通过在check_call外面加上try: except CalledProcessError:语句来实现,但这样又导致出现500错误页面。那部分被注释掉的代码对我也没用。

从/var/www/apache2/error_log中看到的内容:

Wed Apr 13 10:08:21 2011] [error] [client ::1] sox FAIL formats: can't open input file `/tmp/wavs/haha/f.wav': WAVE: RIFF header not found, referer: http://localhost/~Valkyrie_savage/
[Wed Apr 13 10:08:21 2011] [error] [client ::1] malformed header from script. Bad header=\x1f\x8b\b: downsample.py, referer: http://localhost/~Valkyrie_savage/

我不明白为什么它似乎在打印头部之前就运行了sox命令。或者,如果确实是这样,为什么会说头部格式错误呢?

3 个回答

0

你可以使用 subprocess.check_call 这个功能,并且可以捕捉到 CalledProcessError 这个错误。

try:
    retcode = subprocess.check_call(sox)
except CalledProcessError:
    print '<b>something went wrong in sox: returned error code ' +\
      retcode + ', but we are continuing anyway...</b>'
2
import subprocess
p = subprocess.Popen(cmd)  
   p.wait()  
   if p.returncode:  
      print "failed with code: %s" % str(p.returncode) 

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

1

听起来你在使用缓冲输出。

如果是这样的话,命令的输出会在HTTP头信息之前打印出来,这样网页浏览器就会搞混了。

你可以在进行系统调用之前,先调用 sys.stdout.flush(),这样可以确保所有的头信息和HTML内容都已经被真正打印出来。

希望这对你有帮助。

撰写回答