我知道,根据它的定义,一个致命的异常应该会杀死执行,不应该被压制,但这就是问题。
我正在运行一个脚本,在数据库中擦除,解析和存储大约10,000页。这需要几个小时,在极少数情况下(1000个中有1个)页面无法解析并抛出致命异常。
目前,我正在这样做:
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);
}
我可以做点什么吗
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;
}
}
上述代码不适用于fatal exceptions
。
是否有可能做到这样的事情:
如果我将主循环移动到方法中,然后从register_shutdown_function
?
像这样:
function do($start)
{
for($i=$start;$i<$count;$i++)
{
//do stuff here
}
}
register_shutdown_function('shutdown');
function shutdown()
{
do();
}
这是执行停止时输出的消息:
Fatal error: Call to a member function find() on a non-object in ...
当我正在使用的方法无法解析页面时,我希望上面的消息。我很好,只是跳过该页面并继续循环的下一次迭代。
答案 0 :(得分:11)
致命错误是致命的并终止执行。如果发生致命错误,则无法解决此问题。但是,您的错误:
致命错误:在......
中的非对象上调用成员函数find()
完全可以预防。只需添加一个检查以确保您拥有正确对象的实例,如果没有,则处理错误:
if ($foo instanceof SomeObject) {
$foo->find(...);
} else {
// something went wrong
}
答案 1 :(得分:6)
首先,exceptions和errors之间存在明显差异。您遇到的是错误,而不是例外。根据您的消息和您发布的代码,问题在于您没有提出问题。您尝试拨打find()
的变量是什么?好吧,那个变量不是一个对象。没有办法捕获致命错误并忽略它,你必须找到你在非对象上调用find()
的位置并修复它。
答案 2 :(得分:1)
对我而言,似乎唯一可能的方法是“捕获”一个错误,就是注册一个关机功能。请记住将所有(或可能是一组)查询添加到事务中,如果出现故障可能会将其回滚,以确保一致性。
答案 3 :(得分:1)
我遇到了类似的问题,我发现在find()调用之前使用is_object()调用可以避免致命错误。