2012-04-27 18 views
4

永続的な/キャッシュされたスクリプトを作成しようとしています。永続的なperlスクリプトの作成

value=`perl my_script.pl`; 

を次のようにループでシェルスクリプトから呼び出されます

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

が、私はそれように、このスクリプトを呼び出すことができます方法はあり:コードは次のようになりますその状態を維持します。コールからコールへ。 '%my_hash'の初期化とextract_values_from_fileの呼び出しの両方が高価な操作であると仮定します。

ありがとうございました

+1

IMOこれは、スクリプトの使用頻度によって異なります。今すぐ実行する場合は、シリアライゼーション手法を使用してください。それ以上の場合 - 例えば、何らかの重要なリアルタイムの相対的な目的に役立っている - それを永続的なバックグラウンドサーバ/ IPCを使用するようにする。 – delicateLatticeworkFever

答えて

6

あなたの例の%my_hashが最終初期化された状態で適度な大きさを持っている場合は、単に実行間の事前組み立てられた形態でデータを保持するためにStorableJSON::XSまたはData::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__セクションを上書きします。もちろん、スクリプトを実行しているユーザーは、スクリプトに対する書き込み権限を持っている必要があります。

BEGINブロックの代わりにINITブロックを使用するように編集されました.-コンパイルフェーズ中にDATAブロックがセットアップされていません。

+5

状態をシリアル化する - はい。あなた自身の中にそれを書き直してください - 大したことはありません!これはファンキーに見えるかもしれません+ 1または2をもたらすが、それは維持するために完全な混乱です。 –

+3

非常にクールですが、あなたの実際のソースコードファイルに印刷することは健康ではないようです。 – TLP