2012-04-27 79 views
4

我正在尝试编写一个持久性/高速缓存的脚本。该守则将是这个样子:编写持久性perl脚本

... 
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

IMO取决于脚本的使用频率。如果它只是偶尔运行,请使用序列化技术。如果它不止于此 - 例如它正在服务某种关键的或许是实时的相对目的 - 使它成为一个持久的后台服务器/使用IPC。 – delicateLatticeworkFever 2012-04-27 17:51:28

回答

6

如果在你的榜样%my_hash在其最后的初始化状态大小适中,你可以简单地使用的序列化模块中的一个像StorableJSON::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. 

同样可以通过冷冻/解冻

8

实现这是一种黑暗魔法,但你可以在将脚本的__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块在编译阶段未设置。

+5

序列化状态 - 是的。重写它在你自己 - 大大该死的不!这可能看起来很时髦,会产生一两个或两个,但它是一个完整的混乱维护。 – 2012-04-27 15:32:40

+3

非常酷,但打印到您的实际源代码文件似乎不健康。 – TLP 2012-04-27 17:24:17