in reply to Re^2: Filehandle in subroutine in use VRML.pm
in thread Filehandle in subroutine in use VRML.pm

Hi smittypaddler,

Again, you should use all strictures. use strict 'vars'; limits strict checking. use strict; is what you want.

The code change that I gave you for printout() is correct. printout()won't work without that change. Past that, the problem is how you call printout().

You cannot pass a simple bareword file handle like STDOUT as a parameter. Bareword filehandles are global in scope and don't need to be passed as parameters because they are known everywhere, in all subroutines. If you want to pass filehandles as a parameter, you should use lexically scoped filehandles (using "my") which can be passed as parameters. Also as a style rule, whatever level of the program opens a file, that level should be responsible for closing it.
In your case, I would move the opening of the Lumber File up to the main program level. There is no need to ever create the "bareword filehandle, LH". Start off by creating a lexical filehandle to begin with and you don't have to worry about "translating" bareword to normal variable.

my $LumberFile="$Dir/$Subdir/lumber.wrl"; open my $Lumber_fh, '<', $LumberFile or warn "Ooops Cannot Open Lumbe +r File: $LumberFile !! \n Proceeding using STDOUT"; my $out_fh = *STDOUT unless (defined $Lumber_fh); ... As a style point, I add "_fh" ("filehandle") as a suffix to remind myself that this variable is a filehandle and not some integer or other thing. The "*" in front of STDOUT is critical! This allows the "translation" of the bareword filehandle STDOUT into the lexical program variable "my $out_fh". Without that, Perl figures that STDOUT is a string. Now you can pass $out_fh as a parameter to other subs or use it yourself, e.g. print $out_fh "something";
printout() is not needed. A single line suffices and is more clear.
print $out_fh "$_\n" for @lines;

Update:
The error processing above is rather crude and I don't recommend it. In general, if there is a directory path that is supposed to be the "output file" and you can't open it, you should "die" and await changes to that filename/permissions. Normally you would not keep going and "waste" what might potentially be a significant computation effort. I would treat a null string $LumberFile name and non-null string $LumberFile differently.

You might find amusing: A long time ago, when I was working with IBM mainframes, we had a job that ran for 5 days straight. That did not alarm us. We expected that. The unexpected part came when program abended due to a simple JCL (Job Control Language) error before writing the result to a magnetic tape. We had about 16 tape drives on that machine and it would have been completely fine for the program to "open" one of the drives for 5 days and hang on to it. The coding error that involved acquiring a tape drive for output wasn't apparent until after 5 days of number crunching! We lost 5 days of computing, the cost of which was not insignificant. So, in general I would open the output file before I had calculated some result to output to it.

Replies are listed 'Best First'.
Re^4: Filehandle in subroutine in use VRML.pm
by bliako (Abbot) on Jul 12, 2022 at 12:03 UTC
    So, in general I would open the output file before I had calculated some result to output to it.

    For me it's a dilemma. Either: the case you described or ending up with an empty file created on disk after each error in between, which I then try to delete after each of the numerous error/abort conditions. Not an ideal world. Of course there's Perl's END{} but not all languages provide this.