编写一个持久化的Perl脚本

5
我试图编写一个持续/缓存脚本。代码将类似于以下内容:
...
Memoize('process_fille');
print process_file($ARGV[0]);
...
sub process_file{
    my $filename = shift;
    my ($a, $b, $c) = extract_values_from_file($filename);
    if (exists $my_hash{$a}{$b}{$c}){
        return $my_hash{$a}{$b}{$c};
    }
    return $default;
}

以下是在shell脚本中循环调用的代码:

value=`perl my_script.pl`;

有没有一种方法可以调用这个脚本,使其在多次调用之间保持状态。假设初始化“%my_hash”和调用“extract_values_from_file”都是昂贵的操作。谢谢。

1
在我看来,这取决于脚本的使用频率。如果只是偶尔运行,请使用序列化技术。如果不止如此——例如,它正在提供某种关键的、实时相关的目的——请将其作为持久化后台服务器/使用IPC。 - CodeClown42
4个回答

14

这有点像黑魔法,但你可以在脚本的__DATA__标记之后存储状态并使其持久化。

use Data::Dumper; # or JSON, YAML, or any other data serializer
package MyPackage;
my $DATA_ptr;
our $state;
INIT {
    $DATA_ptr = tell DATA;
    $state = eval join "", <DATA>;
}

...
manipulate $MyPackage::state in this and other scripts
...

END {
    open DATA, '+<', $0;   # $0 is the name of this script
    seek DATA, $DATA_ptr, 0;
    print DATA Data::Dumper::Dumper($state);
    truncate DATA, tell DATA;  # in case new data is shorter than old data
    close DATA;
}
__DATA__
$VAR1 = {
    'foo' => 123,
    'bar' => 42,
    ...
}
INIT块中,记录文件的__DATA__章节起始位置并反序列化状态。在END块中,重新序列化当前状态并覆盖脚本的__DATA__章节。当然,运行脚本的用户需要对脚本拥有写入权限。
编辑使用INIT块而不是BEGIN块--DATA块在编译阶段未设置。

6
序列化状态 - 是的。在自己内部重新编写 - 绝对不行!这可能看起来很新奇,可以获得一两个额外点数,但是它非常难以维护。 - Oleg V. Volkov
3
非常酷,但似乎将内容打印到实际的源代码文件中不太健康。 - TLP

6
如果您的示例中的%my_hash在其最终初始化状态中具有适度的大小,则可以简单地使用其中一个序列化模块(如Storable, JSON::XSData::Dumper)将数据保留在预组装形式之间运行。当文件不存在时生成新文件,当存在时只需从那里重新加载准备好的内容即可。

此外,您提到您会在循环中调用此脚本。一个好的策略是不要立即在循环内调用脚本,而是构建参数队列,然后在循环后将所有参数传递给脚本进行单个执行。脚本将设置其环境,然后循环遍历参数,执行其易于处理的工作,无需为每个参数重新执行设置步骤。


2

您无法让脚本保持状态。一旦进程退出,未写入磁盘的任何信息都会消失。

但是有几种方法可以实现这个目标:

  • 编写一个守护进程,监听网络或Unix套接字。该守护进程可以填充 my_hash 并回答来自非常简单的 my_script.pl 发送的问题。它只需要打开到守护进程的连接、发送问题并返回答案即可。

  • 创建一个高效的查找文件格式。如果您经常需要这些信息,则它很可能会留在VFS缓存中。

  • 设置共享内存区域。您的脚本第一次启动时将信息保存在那里,然后稍后重复使用。不过,从Perl脚本中实现可能有点棘手。


0

不可以直接实现,但有很多方法可以达到目的。

1) I understand **extract_values_from_file()** parses given file returning hash.
2) 1 can be made as a script, then dump the parsed hash using **Data::Dumper** into file.
3) When running my_script.pl, ensure that file generated by 2 is later than of the config file. Can achieve this via **make**
3.1) **use** the file generated by 2 to retrieve values.

可以通过冻结/解冻来实现相同的效果


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接