I'm the author of Pythonizer and I'm trying to translate the code of CGI.pm from the standard perl library to Python. I came across this code in read_from_client:
read(\*STDIN, $$buff, $len, $offset)
Is \*STDIN
the same thing as just STDIN
? I'm not understanding why they are using it this way. Thanks for your help!
The module also references \*main::STDIN
- is this the same as STDIN
too (I would translate plain STDIN
to sys.stdin
in python)? Code:
foreach my $fh (
\*main::STDOUT,
\*main::STDIN,
\*main::STDERR,
) { ... }
CodePudding user response:
Instead of translating CGI.pm line for line, I'll recommend you understand the interface then do whatever Python would do for that. Or, better yet, just forget it exists. It often seems like a translation will be a drop-in replacement, but since the libraries and structures you'll use in the new language are different enough that you are just going to make new bugs. Since you are going to make new bugs anyway, you might as well do something smarter.
But, I know nothing about your situation, so let's get to the literal question.
You're looking at:
# Read data from a file handle
sub read_from_client {
my($self, $buff, $len, $offset) = @_;
local $^W=0; # prevent a warning
return $MOD_PERL
? $self->r->read($$buff, $len, $offset)
: read(\*STDIN, $$buff, $len, $offset);
}
Instead of worrying about the Perl code, just do whatever you need to do in Python to satisfy the interface. Given a buffer and a length, get some more data from the filehandle. Since you are not handling mod_perl (I'm guessing, because how would you?), you can ignore most stuff there.
The \*main::STDIN
and \*STDIN
are references to a typeglob, which is a way to track all the Perl variables with the same name (scalar, array, hash, subroutine, filehandle, and a few others). The STDIN
identifier is a special case variable that is main
by default, so adding the package main::
in front is probably merely developer comfort.
When you use those reference in a place that wants to work on a filehandle, the filehandle portion of the type glob is used. It's just a way to pass the identifier STDIN
and have something else use it as a filehandle.
You see this as a way to pass around the named, standard file handles.
The read
takes a filehandle (or reference to typeglob) as its first argument.
In python, you'd do something like sys.stdin.read(...)
.
CodePudding user response:
The following can usually be used a file handle:
- An IO object (
*STDIN{IO}
) - A glob containing an IO object (
*STDIN
) - A reference to a glob containing an IO object (
\*STDIN
) - The name of a glob containing an IO object (
"STDIN"
)
The builtin operators that expect a file handle allow you to omit the *
when providing a glob. For example, read( FH, ... )
means read( *FH, ... )
.
The builtin functions that expect a file handle should accept all of these. So you could any of the following:
read( *STDIN{IO}, ... )
read( STDIN, ... )
read( *STDIN, ... )
read( \*STDIN, ... )
read( "STDIN", ... )
.
They will have the same effect.
Third-party libraries probably accept the globs and reference to globs, and they should also expect IO objects. I expect the least support for the providing the name as a string. Your mileage may vary.
You can't go wrong with a reference to a glob (\*FH
) since that's what open( my $fh, ... )
produces.