如何在subprocess中启动崩溃(很less)的应用程序

我有python应用程序需要执行专有的应用程序(它不时崩溃)每天约20 000次。

问题是当应用程序崩溃,Windows会自动触发WerFault ,这将保持程序挂起,因此python的subprocess.call()将永远等待用户input(应用程序必须在周末,节假日,24/7运行…所以这是不能接受的)。

如果要sleep; poll; kill; terminate sleep; poll; kill; terminate sleep; poll; kill; terminate但这意味着使用communicate() ,应用程序可以运行从几个毫秒到2小时,所以设置固定超时将无效

我也尝试开启自动debugging (使用一个脚本,将采取一个应用程序的崩溃转储和终止id),但不知何故这个howto不工作在我的服务器(WerFault仍然出现,等待用户input)。

其他几个教程也没有任何效果。

问题 :如何防止WerFault显示(等待用户input)? 这是更系统的编程问题

另一个问题 :是否有一个在Python中优雅的方式如何检测应用程序崩溃(是否显示WerFault

Solutions Collecting From Web of "如何在subprocess中启动崩溃(很less)的应用程序"

简单(和丑陋)的答案,不时监测WerFault.exe实例,特别是与违规应用程序的PID相关的一个。 杀了它 处理WerFault.exe是复杂的,但你不想禁用它 – 请参阅Windows错误报告服务。

  1. 获取与WerFault.exe相匹配的进程名称列表。 我使用psutil包。 因为进程被缓存,所以要小心psutil ,使用psutil.get_pid_list()
  2. 通过使用argparse解码它的命令行。 这可能是矫枉过正,但它利用现有的Python库。
  3. 根据PID确定持有应用程序的进程。

这是一个简单的实现。

 def kill_proc_kidnapper(self, child_pid, kidnapper_name='WerFault.exe'): """ Look among all instances of 'WerFault.exe' process for an specific one that took control of another faulting process. When 'WerFault.exe' is launched it is specified the PID using -p argument: 'C:\\Windows\\SysWOW64\\WerFault.exe -u -p 5012 -s 68' | | +-> kidnapper +-> child_pid Function uses `argparse` to properly decode process command line and get PID. If PID matches `child_pid` then we have found the correct parent process and can kill it. """ parser = argparse.ArgumentParser() parser.add_argument('-u', action='store_false', help='User name') parser.add_argument('-p', type=int, help='Process ID') parser.add_argument('-s', help='??') kidnapper_p = None child_p = None for proc in psutil.get_pid_list(): if kidnapper_name in proc.name: args, unknown_args = parser.parse_known_args(proc.cmdline) print proc.name, proc.cmdline if args.p == child_pid: # We found the kidnapper, aim. print 'kidnapper found: {0}'.format(proc.pid) kidnapper_p = proc if psutil.pid_exists(child_pid): child_p = psutil.Process(child_pid) if kidnapper_p and child_pid: print 'Killing "{0}" ({1}) that kidnapped "{2}" ({3})'.format( kidnapper_p.name, kidnapper_p.pid, child_p.name, child_p.pid) self.taskkill(kidnapper_p.pid) return 1 else: if not kidnapper_p: print 'Kidnapper process "{0}" not found'.format(kidnapper_name) if not child_p: print 'Child process "({0})" not found'.format(child_pid) return 0 

现在, taskkill函数以正确的PID调用taskkill

 def taskkill(self, pid): """ Kill task and entire process tree for this process """ print('Task kill for PID {0}'.format(pid)) cmd = 'taskkill /f /t /pid {0}'.format(pid) subprocess.call(cmd.split()) 

我没有理由为什么你的程序需要崩溃,找到有问题的代码片段,并把它放到try-statement中。

http://docs.python.org/3.2/tutorial/errors.html#handling-exceptions