Catch a fatal exception and continue

人盡茶涼 提交于 2019-12-07 02:04:30

问题


I know, that by its very definition, a fatal exception is supposed to kill the execution, and should not be suppressed, but here's the issue.

I'm running a script that scrapes, parses and stores in a DB about 10,000 pages. This takes a couple of hours, and in rare cases (1 in 1000) a page fails parsing and throws a fatal exception.

Currently, I'm doing this:

for ($i=0;$i<$count;$i++)   
        {
            $classObject = $classObjects[$i];           

            echo $i . "   :   " . memory_get_usage(true) . "\n";

            $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap);           
            $class = $parser->parseClassInfo($classDOM);                    
            $dbmanager->storeClassInfo($class);         

            unset($classDOM,$class,$classObject);           
        }        

Can I do something like

for ($i=0;$i<$count;$i++)   
{
   $classObject = $classObjects[$i];            
   echo $i . "   :   " . memory_get_usage(true) . "\n";

   try
   {
      $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap);         
      $class = $parser->parseClassInfo($classDOM);                  
      $dbmanager->storeClassInfo($class);           
      unset($classDOM,$class,$classObject);         
    }
    catch (Exception $e)
    {
       //log the error here
       continue;
    }
}

The code above doesn't work for fatal exceptions.

Would it be possible to do something like this: If I moved the main loop into a method, and then call the method from register_shutdown_function ?

Like this:

function do($start)
{
   for($i=$start;$i<$count;$i++)
   {
      //do stuff here
   }
}

register_shutdown_function('shutdown');

function shutdown()
{ 
   do();
}

This is the message that is output when execution stops:

Fatal error:  Call to a member function find() on a non-object in ...

I expect this above message when a page isn't parse-able by the method I am using. I'm fine with just skipping that page and moving on to the next iteration of the loop.


回答1:


Fatal errors are fatal and terminate execution. There is no way around this if a fatal error occurs. However, your error:

Fatal error: Call to a member function find() on a non-object in ...

is entirely preventable. Just add a check to make sure you have an instance of the correct object, and if not, handle the error:

if ($foo instanceof SomeObject) {
    $foo->find(...);
} else {
    // something went wrong
}



回答2:


First, there is a distinct difference between exceptions and errors. What you encountered is an error, not an exception. Based on your message and the code you posted the problem is with something you haven't put into your question. What variable are you trying to call find() on? Well, that variable isn't an object. There is no way to trap fatal errors and ignore it, you must go find where you are calling find() on a non-object and fix it.




回答3:


Seems to me like the only possible way to "catch" a faltal error is with the registering a shutdown function. Remember to add all (or maybe groups of) queries into transactions and maybe roll them back if something fails, just to ensure consistency.




回答4:


I have had a similar problem to this, and I found that using a is_object() call before the find() call allows you to avoid the fatal error.



来源:https://stackoverflow.com/questions/8839173/catch-a-fatal-exception-and-continue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!