简体   繁体   English

Perl 中的“句柄”是什么?

[英]What is a "handle" in Perl?

Wondering what the handle is in Perl.想知道 Perl 中的手柄是什么。

I can see file handle, directory handle..etc but want to know the meaning of the handle in Perl.我可以看到文件句柄,目录句柄..等,但想知道 Perl 中句柄的含义。

For example, in IO::Pipe, I can see below explain.例如,在 IO::Pipe 中,我可以看到下面的解释。 And want to make clear the meaning of "becomes a handle"?并想明确“成为手柄”的含义?

reader ([ARGS])

The object is re-blessed into a sub-class of IO::Handle, 
and becomes a handle at the reading end of the pipe. If 
ARGS are given then fork is called and ARGS are passed 
to exec.

Also could you please explain the meaning of bless?另外,请您解释一下祝福的含义吗?

A handle is an way to get to something without actually being that thing.句柄是一种到达某物的方法,而不是真正成为那个东西。 A handle has an interface to interact with something managed by system (or something else).句柄有一个接口来与系统管理的东西(或其他东西)进行交互。

Start with the idea of a scalar.从标量的概念开始。 Defining a simple scalar stores a value and that value is actually in the memory of your program.定义一个简单的标量存储一个值,该值实际上位于程序的 memory 中。 In very simplistic terms, you manage that resource directly and wholly within your program.用非常简单的术语来说,您可以直接在您的程序中完全管理该资源。 You don't need to ask the system to do increment the variable for you:您无需要求系统为您增加变量:

 my $n = 5; 
 $n++;

Talking to the outside world与外界对话

A handle represents a connection to something managed by something else, typically through "system calls".句柄表示与由其他事物管理的事物的连接,通常通过“系统调用”。

A file handle is your connection to a file (so, managed by the filesystem or OS) but is not the file itself.文件句柄是您与文件的连接(因此,由文件系统或操作系统管理),但不是文件本身。 With that filehandle, you can can read from or write to the file, there is code behind all that to talk to the system to do the actual work.使用该文件句柄,您可以读取或写入文件,所有这些背后都有代码可以与系统对话以完成实际工作。

 open my $filehandle, '<', $filename or die "$!";

Since you are not managing the actual work and since you depend on the system to do the work, you check the $!由于您没有管理实际工作,并且由于您依赖系统来完成工作,因此您检查$! system error variable to check that the system was able to do what you wanted.系统错误变量以检查系统是否能够执行您想要的操作。 If it couldn't, it tells you how it ran into a problem (although the error may not be very specific).如果不能,它会告诉您它是如何遇到问题的(尽管错误可能不是很具体)。

A directory handle is a way to get a list of the things inside a directory, but is not the directory itself.目录句柄是一种获取目录内事物列表的方法,但不是目录本身。 To get that, you have to ask the system to do things for you.为此,您必须要求系统为您做事。 And so on.等等。

Perl is wonderful though Perl 虽然很棒

But, in Perl, you can make a handle to anything you like (and I write a lot about this in either Effective Perl Programming and Mastering Perl . You can use the interface for a handle even if you wholly control the thing and don't need to ask the system to do something on your behalf.但是,在 Perl 中,您可以处理任何您喜欢的事情(我在有效的 Perl 编程掌握 Perl中写了很多关于此的内容。即使您可以完全控制该接口,也可以使用您完全控制的接口。需要要求系统代表您做某事。

For example, you can use the filehandle interface on a string:例如,您可以在字符串上使用文件句柄接口:

 open my $string_filehandle, '>', \my $string;
 print {$string_filehandle} "This goes to the string";

To your code as you read it, it looks like the thing is a file (socket, whatever) because the main use of the handle interface.对于您阅读的代码,它看起来像是一个文件(套接字,无论如何),因为主要使用句柄接口。 This is quite handy when your are handcuffed to using a filehandle because someone else wrote some code you can't change.当您被束缚于使用文件句柄时,这非常方便,因为其他人编写了一些您无法更改的代码。 This function is designed to only send $message to some output handle:此 function 旨在仅向某些 output 句柄发送$message

sub print_to_file_only {
    my( $filehandle, $message ) = @_;
    print {$filehandle} $message;
    }

But sometime you don't want that message to go to the terminal, file, socket, or whatever.但是有时您不希望将 go 的消息发送到终端、文件、套接字或其他任何东西。 You want to see it in my program.你想在我的程序中看到它。 You can capture the message in your $string_filehandle because it uses the same handle interface even though it's not a static resource.您可以在$string_filehandle中捕获消息,因为它使用相同的句柄接口,即使它不是 static 资源。

print_to_file_only( $string_filehandle );

Now you'll see the message show up in $string , and you can do whatever you like with it.现在您将看到消息显示在$string中,您可以使用它做任何您喜欢的事情。

There are many more tricks like this, and I'm tempted to talk about all of them.像这样的技巧还有很多,我很想谈论所有这些技巧。 But, this should be a good start.但是,这应该是一个好的开始。

This can be a very broad topic and I'll try to stay with the crux of the question, captured in a line from IO::Pipe docs这可能是一个非常广泛的话题,我将尝试抓住问题的症结所在,从IO::Pipe文档中捕获

The object is re-blessed into a sub-class of IO::Handle , and becomes a handle at the reading end of the pipe. object 被重新加持为IO::Handle的子类,成为 pipe 读取端的句柄。

A "handle" in Perl is a construct built around some resource, out in the OS or in our program, which allows us to manage that resource. Perl 中的“句柄”是围绕某些资源构建的,在操作系统或我们的程序中,它允许我们管理该资源。 A filehandle, for instance, may facilitate access to a file, via libraries and OS facilities, and is more than a plain file descriptor.例如,文件句柄可能有助于通过库和操作系统工具访问文件,并且不仅仅是一个普通的文件描述符。

use warnings;
use strict;
use feature 'say';

open my $fh, '<', $file or die "Can't open $file: $!";
say fileno $fh;   # file descriptor, a small integer, normally >= 3
say $fh->fileno;  # can use handle as object of IO::Handle or IO::File
close $fh;

The opened file got a file descriptor in the OS, a small integer, the first one available.打开的文件在操作系统中有一个文件描述符,一个小的 integer,第一个可用的。 But we get the "filehandle" $fh associated with the opened file, which is far nicer to work with and with which various tools can be used. 但是我们得到了与打开的文件关联的“文件句柄” $fh ,它更易于使用,并且可以使用各种工具。 (The fileno was used to get the fd from it.) fileno用于从中获取 fd。)

In newer Perls ( since v5.14.0 ) a (file)handle can in fact be treated as an object of IO::Handle or IO::File , as these classes will be loaded on demand once a method call from them is used on the variable with the handle (if the call can't be found otherwise).在较新的 Perls( 自 v5.14.0 起)中,(文件)句柄实际上可以被视为IO::HandleIO 的 object::Handle 或 IO:带有句柄的变量(如果无法找到调用)。

This brings us to the second question, of "re-bless"-ing.这就把我们带到了第二个问题,“再祝福”。

When a reference is bless -ed "into" a package it becomes an object of (the class supposedly defined in) that package. When a reference is bless -ed "into" a package it becomes an object of (the class supposedly defined in) that package. This is normally done in the constructor and such "blessed" reference is returned to the caller and that is an "instance" of that class in the caller, an object.这通常在构造函数中完成,并且这样的“祝福”引用返回给调用者,这是调用者中 class 的“实例”,即 object。

It then "knows" what package it's from (its internal structure has extra fields for that), one can call methods defined in the package on it, etc. This is a bit oversimplified, go read perlootut and perlobj for starters. It then "knows" what package it's from (its internal structure has extra fields for that), one can call methods defined in the package on it, etc. This is a bit oversimplified, go read perlootut and perlobj for starters.

The quote from the docs comes from the reader or writer methods in IO::Pipe class.文档中的引用来自IO::Pipe class 中的readerwriter器方法。 Once they are called on an object of that class it becomes beneficial for the object to have facilities from IO::Handle , so it is "made" into an object of that class. Once they are called on an object of that class it becomes beneficial for the object to have facilities from IO::Handle , so it is "made" into an object of that class. (Not of IO::File class since a pipe isn't seekable while IO::File inherits from IO::Seekable as well.) (Not of IO::File class since a pipe isn't seekable while IO::File inherits from IO::Seekable as well.)

Since bless is a crucial and telling part of the process peopple often simply say that it's "blessed" (or "re-blessed" here since it was an object of a class), but as you can see from the linked sources there is a bit more to do.由于bless是过程中至关重要且有说服力的部分,人们通常会简单地说它是“blessed”(或在这里“re-blessed”,因为它是一个类的 object),但正如您从链接资源中看到的那样,有一个更多的事情要做。

As a final comment, note that a "(file)handle" can be opened to things entirely other than an OS resource like a file/socket (etc).作为最后的评论,请注意“(文件)句柄”可以完全打开文件/套接字(等)等操作系统资源以外的东西。 For example, it can be "tied" (see perltie , Tie::Handle );例如,它可以被“捆绑”(参见perltieTie::Handle ); or, open ed to a scalar ("in-memory file").或者, open ed 到一个标量(“内存文件”)。 § §


If STDIN / STDOUT / STDERR (fd's 0,1,2) aren't closed and this is the first thing opened, it gets 3 如果STDIN / STDOUT / STDERR (fd 的 0,1,2) 没有关闭并且这是第一个打开的东西,它得到3

The IO::File inherits from IO::Handle and IO::Seekable , adding only a few methods. IO::File继承自IO::HandleIO::Seekable ,仅添加了一些方法。 Most classes that represent various handles, like IO::Pipe or IO::Select , inherit from IO::Handle . Most classes that represent various handles, like IO::Pipe or IO::Select , inherit from IO::Handle . So the docs for that, first, provide a feel for what is available for a "handle."因此,首先,有关该文档的文档提供了对“句柄”可用内容的感觉。

§ This isn't a full filehandle though; §这不是一个完整的文件句柄; try fileno on it ( -1 ).尝试fileno-1 )。 But it behaves well enough to be useful.但它的表现足够好,可以派上用场。 One example: I use it in forked processes to accumulate prints in a child in a string, which is in the end sent over to the parent.一个例子:我在分叉的进程中使用它来在一个字符串中累积一个子进程的打印,最终发送给父进程。 That way they can be logged/printed coherently, and in some order.这样,它们就可以连贯地以某种顺序记录/打印。

# in a child
my $stdout;  # redirect STDOUT writes to it, then pass via pipe
open my $fh_stdout, '>', \$stdout  or croak "Can't open var for write: $!";
my $fh_STDOUT = select $fh_stdout;  # switch default to it, save old (STDOUT)

say "goes to string";  # winds up in $stdout, in the end sent to parent

select $fh_STDOUT;  # cna switch back to STDOUT (normally not needed in child)

This can be done in other ways of course (just append to a string instead of printing) but this way we get normal prints once the handle is select -ed as default, so can use existing subs/libraries etc.这当然可以通过其他方式完成(只是 append 到一个字符串而不是打印)但是一旦句柄是select作为默认值,我们就会得到正常的打印,所以可以使用现有的子/库等。

Most languages create variables and objects in very different ways.大多数语言以非常不同的方式创建变量和对象。 In Perl , they are very similar.Perl中,它们非常相似。

Perl allows most types of variables to be marked as an object by the bless functionality. Perl允许大多数类型的变量被 bless 功能标记为 object。

This confer additional powers to the variable to call methods in the class.这赋予变量额外的权力来调用 class 中的方法。 Perl will search that class for a method of that name. Perl将在 class 中搜索该名称的方法。 If you fail to supply the second argument to bless , it will use the current package or class to search.如果您没有提供第二个参数bless ,它将使用当前的 package 或 class 进行搜索。

In their IO::Pipe example, you call IO::Pipe 's new() method to obtain a blessed object. In their IO::Pipe example, you call IO::Pipe 's new() method to obtain a blessed object. To them make use, they fork() and the parent converts ("re-blessed") $pipe to a reader subclass of IO::Pipe with methods calls that work as a reader.对他们来说,他们使用 fork() 和父级转换(“重新祝福”) $pipeIO::Pipe的读取器子类,方法调用用作读取器。 The child process converts their $pipe to a write.子进程将其$pipe转换为写入。 Now they may communicate from child to parent via the pipe.现在他们可以通过 pipe 从孩子到父母进行交流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM