看似随机的Perl错误

时间:2015-03-17 14:09:04

标签: perl

我的Perl程序包含两个与此类似的块:

open my $file, '>', $filename or do{
    print "Failed to open file\nFile not saved\n";
    return;
}

当我运行它时,我得到了这个:

"my" variable @lines masks earlier declaration in same scope at myfile.pl line 43.
"my" variable @args masks earlier declaration in same scope at myfile.pl line 43.
"my" variable @args masks earlier declaration in same statement at myfile.pl line 43.
"my" variable @args masks earlier declaration in same scope at myfile.pl line 47.
syntax error at myfile.pl line 19, near "$i ("
Global symbol "$i" requires explicit package name at myfile.pl line 20.
Global symbol "$file" requires explicit package name at myfile.pl line 21.
Global symbol "$i" requires explicit package name at myfile.pl line 21.
Global symbol "$file" requires explicit package name at myfile.pl line 23.
syntax error at myfile.pl line 24, near "}"
syntax error at myfile.pl line 35, near "}"
syntax error at myfile.pl line 44, near "}"
syntax error at myfile.pl line 54, near "}"
Can't use global @_ in "my" at myfile.pl line 57, near ", $_"
myfile.pl has too many errors.

但是当我用它替换它时:

do{
    print "Failed to open file\nFile not saved\n";
    return;
}unless open my $file, '>', $filename;

所有错误立即消失,程序运行正常。我有use strictuse warnings

有谁知道为什么会这样?我的括号有什么问题吗?更改open函数中的间距不起作用。

编辑:我已将print语句替换为warn

2 个答案:

答案 0 :(得分:3)

在第一种情况下

open ( my $file, '>', $filename ) or do {
  print "Failed to open file\nFile not saved\n";
  return;
}

my $filedo块之外的范围内,而在

do {
  print "Failed to open file\nFile not saved\n";
  return;
} unless open my $file, '>', $filename;

它是块的本地。请注意,这也意味着您在打开它之后无法使用$file来写入,因为它会立即再次关闭。

你可以

  • 为每个文件句柄使用不同的标识符

  • 在第一次

  • 之后忽略所有my来电中的open
  • 将每个open及后续文件操作包含在其自己的块中,如下所示

    {
      open( my $file, '>', $filename ) or do{
        print "Failed to open file\nFile not saved\n";
        return;
      };
    
      # Write to $file
    }
    

答案 1 :(得分:0)

我认为这与子程序有关。否则,为什么你有return

使用标准if声明。这样,程序正在做的更清楚:

my $file;
if ( not open $file, ">", $filename ) {
    warn qq(Failed to open file "$filename"\nFile not saved\n);
    return;
}

注意:

  • 我必须在$file之外定义if。否则,$fileif之外变为未定义。可能不是你想要的。 (并且是造成问题的原因)。
  • 我也使用warn。这会打印到STDERR而不是STDOUT。它还会警告开发人员浏览代码,这是某种错误消息,可能需要注意。

最新的样式编程风格是让子程序死于错误。这意味着您可以在子例程中执行此操作:

open my $fh, ">", $filename
     or die qq(Can't open "$filename"\n);

现在,如果开发人员不希望程序死亡,开发人员现在必须使用eval来主动处理错误:

my $fh;
eval {
     $fh = openlog ( $filename );
};
if ( $@ ) {
     warn qq(Can't open log file "$filename". No log will be written);
}

这是异常处理编程语言(如Python和Java)强制开发人员面对错误的方式。否则,开发人员可以简单地假设子例程有效。在Perl中,你会一直看到这样的东西:

send_email( email_address( $user ), $message );

嗯......在程序尝试发送电子邮件之前,email_address()是否确实返回了电子邮件地址?