2006年11月26日
stashとconfig
Catalystでの話。
$c->configには普通ConfigLoaderなどで初期値のみを入れて読み出しのみでしか使いませんが、実はこの値、上書き可能だったりします。
そうすると、$c->stashの様にグローバル値として使えるのですが、注意しないといけないのが、この値はstashと異なり、呼び出し単位で初期化されないと言うことです。
まぁ、Catalystのアプリのどこかに
die ++$c->stash->{'test'};と
die ++$c->config->{'test'};のそれぞれを埋め込んで動作を確認して頂ければ解ると思いますが、stashが呼び出しごとに初期化されて必ず1が返るのに対して、configの方ではどんどん数字が増えていきます。
(ただし、サーバ側でアプリが常駐しない仕様になっているとこちらも1になるかと思います)
なら、ちゃんとstashとconfigを使い分ければいいじゃないという話になるのですが、YAMLに記載されたconfig値を読み込んでから加工して戻したいと言った用途の際に困ります。
(たとえばURLリストにベースパスを付加して戻したいと言った用途の場合)
まぁ、戻すときにconfig出はなくstashに戻してそちらを用いる手や使うところで毎回ベースパスを追加すると言う手もあるのですが、せっかく一度読み込んだらその後常駐終了まで保持してくれる値を何度も計算したくないので、こういう場合は自作のPulginを作成してそれのsetupメソッドにconfigの値を操作させれば一度しか呼び出されないので楽です。
あと、自作プラグインはlib/MyApp以下に置くと自動認識されてしまってちゃんと動作しないので、ライブラリのサーチパスのどこかに置いて頭に「+」をつけてモジュール名で指定すると良いみたいです。
と言うか、ここら辺の仕掛けは↓のリンク先を読むのが手っ取り早いです。
2006年10月11日
FormValidator::Simple::Auto
これは、
最初、この問題に気が付かずハマリ、次にこの問題を何とか回避できないかとはまって結果的にかなりの時間を浪費してしまいました。
結論から言うと私はCatalyst::Plugin::FormValidator::Simple::Autoを使うのをすっぱりあきらめました。
(この問題だけ別に記述などして回避したとしても余計ソースが混乱するだけですし)
と言うか、色々やってみてYAMLに記載すべきなのは日本語メッセージなどローカライズに必要なものと、せいぜい簡単なconfig値までにとどめておくべきだと思いました。
何でもYAMLでやりたい人も居るかも知れませんが、一通り使ってみて正規表現の記述の煩雑さやタブが使えないなど微妙な点が多いマイナーなマークアップランゲージを覚えてまで全ての設定を記述すべき必要性は無いかと思います。
(むしろ何かあったら教えてください)
2006年09月30日
YAML::Syckの罠
YAML::SyckがインストールされているとCatalyst::Plugin::ConfigLoaderで正規表現が展開できません。たとえばYAMLでPerlの正規表現を書く場合
なんていう風に書きますが、YAML::Syckが入って居るとfoo: !perl/regexp: REGEXP: '^hoge$'
'foo' => bless( {
'REGEXP' => '^hoge$'
}, 'regexp:' )
},なんていう風に展開されます。ちなみにYAML::Syckなしの場合
と正常に展開されます。'foo' => qr/(?-xism:(?:^hoge$))/
2006年09月28日
Catalyst始めました
久々にPerlでアプリ一つ作ることになりました。
一人開発でそんなに大きいモノではない&クローズドな用途なのでいつも通り適当にフルスクラッチで拵えようかと思ったのですが、体調崩して気が付いたらだいぶ尺が無くなりました。
小物とはいえ、その状態からフルスクラッチ+仕様変更が入ると死ねそうだったのと、Ruby on Railsを知ってからフレームワークでの作成が気になっていた事もあり、一発逆転を狙ってCatalystを導入(笑)
で、この手のフレームワークはPHPのを使うのが相場らしいですが、PHPよりは圧倒的にPerlの方が好きと言うことがあり、あえてPerlのフレームワークを使うことにしました。
(でも、ここが茨の道のスタートライン(笑))
他にもPerlのフレームワークには
で、Catalystのセットアップ方法は各所のサイトを参考にして貰うと言うことで、個人的に困った点だけ。
まずは、インストールがめちゃくちゃ大変。
必要なパッケージがめちゃくちゃ多いのでディストリビューターの方でパッケージを準備していない場合は、RPMインストールはほとんど無理っぽい感じです。
(素のCatalystまでだったらCPAN2RPMなんかを駆使することで何とか入れられそうですが、実際使うためにCatalystのPlug-inを入れようと思うと、それこそのべ100ぐらいのPerlモジュールが必要そうな感じです)
今度こそRPMで全てを管理したかったんですが、結局今回もPerl周りはCPANに依存してしまいました。
続きを読む...2004年08月24日
Text::Iconv
Text::IconvをPerl5.6環境にインストールしようといつも通りPerl -MCPAN -e shellしたところ下記のようなエラーに遭遇
cpan> install Text::Iconv
In string, @DEFINE now must be written as \@DEFINE at Makefile.PL line 89, near "@DEFINE"何がいけないんだろうと思ってとりあえずエラーになった
Execution of Makefile.PL aborted due to compilation errors.
~/.cpan/build/Text-Iconv-1.4/Makefile.PLを見てみると、
WriteMakefile(
'NAME' => 'Text::Iconv',
'VERSION_FROM' => 'Iconv.pm', # finds $VERSION
'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'Iconv.pm', # retrieve abstract from module
AUTHOR => 'Michael Piotrowski <mxp@dynalabs.de>') : ()),
'LIBS' => $config{LIBS},
'DEFINE' => "@DEFINE",
'INC' => $config{INC},
'dist' => {COMPRESS => 'gzip', SUFFIX => 'gz'},
);
なるほど、"@DEFINE"っていう書式が悪いらしい。とりあえず、定数で代入してやればmake出来そうだったのでPerl5.8.0環境でCPANをかけてインストールしてみたところ@DEFINEの中身はNULLで良いようだったので
'DEFINE' => "",と書き換えて今度は手動でmake・・・成功( ̄▽ ̄)ノ
make testも成功したのでmake installでさっくりインストールしました。
2004年05月19日
配列の比較の時に
Perlで配列Aに含まれて居て配列Bに無いものを抽出しようとしてforeach (@arrA){
unless(grep(/^$_$/,@arrB)){
push(@newarr,$_)
}
}
というのを書いたんですが、これがうまく動かない。どうも調べて見ると配列Bが一件も無い場合は良いのですが、配列Bに1件でも要素があると配列Aの要素が全て配列Bにあると判断される模様。
まぁ、世の中には
注意: $_ は配列値への参照となっているので、配列要素を変更するのに用いることができる。これは便利である一方、 LIST が名前のついた配列でない場合には、ちょっと変な結果を返すことがある。
確かに同時に書き換えられたら便利な時もあるけど、かなりハマる仕様だなぁ(苦笑)
というわけで
foreach my $var (@arrA){
unless(grep(/^$var$/,@arrB)){
push(@newarr,$var)
}
}
としたらちゃんと動作するようになりました( ̄▽ ̄)ノ
2004年05月18日
2004年04月10日
CGIのデバッグ
PerlでCGIの作成をしているときに手元じゃちゃんと動くのにサーバに上げると500 サーバーエラーがでてしまうときがあります。
こういうときはWEBサーバのエラーログにどのようなエラーが出たか書いてありますが、サーバによってはエラーログのファイルがユーザには見えないようにしてあることも多々あります。
そういう場合に下記のようなスクリプトをdebug.cgiなどとして保存しサーバにアップロード→パーミッションを755等にしてブラウザからアクセスすると、デバッグしたいCGIの何行目でエラーが起こったのか判るので、デバッグに役に立つかもしれません。
(なお、hoge.cgiの部分には自分がデバッグするcgiの名称に変えておいてください)
#!/usr/bin/perl
open PL, "hoge.cgi";
my @EVALarr = <PL>;
close PL;
my $EVALscript = join('',@arr);
eval $EVALscript;
if ($@) {
print "Content-type: text/html\n\n";
print "<html><body><pre>\n";
print "$@\n";
print "</pre></body></html>\n";
}
あと、上記のスクリプトは開発が終わったらちゃんと削除しておくのが良いです。
2004年03月12日
GetOptions(2)
(1)の続き
前回、各foo、barそれぞれのオプションの引数を文字でとか数値でとかという風に書きましたが、実際は「オプション名=1文字」という書式で1文字の部分(記述子といいます)でどう処理するか決めています。
記述子の対応は以下のようになってます。
| s | 文字列 |
| i | 整数値(負の数を含む) |
| f | 実数値(負の数を含む) |
また、オプション名と記述子の間はイコール(=)で結んでいましたがこれにも意味があり、=で結ぶとオプションの後に必ず対応する引数が必要になります。
もし、オプション名だけでも引数があっても良いようにしたい場合はイコールの部分をコロン(:)にします。
上記をふまえて前回最後のものを書き換えてみます。
use Getopt::Long;
GetOptions("foo:s","bar=f") || die("GetOptions failed");
print "$opt_foo/$opt_bar";
これを実行すると以下のようになります
perl test.pl -foo -bar 123.45続きを読む...
/123.45perl test.pl -foo aaa -bar
Option b requires an argument
GetOptions failed at test.pl line 2.
2004年03月07日
GetOptions(1)
GetOptionsに関するわかりやすい説明が見つからなかったのでちょっとやってみます。まず、もっとも単純な構造は以下の通り
use Getopt::Long;
$ret = GetOptions("foo","bar");
print "$ret:$opt_foo/$opt_bar";
上記の例ではオプション「foo」「bar」があるかどうかを確認出来ますので以下のように
perl test.pl -foo -barと実行すると「1:1/1」と表示されます。
また、下記のようにすると
perl test.pl -bar「1:/1」という結果となり
perl test.plとすると「1:/」という結果になります
成功しても失敗しても全く同じ結果を返してくれるへっぽこ装置操作コマンドを何とかしなければいけなくなりました。
ただ、幸いにも失敗の場合は5秒未満、成功の場合は15秒前後でプログラムが停止してくれるので、実行実時間を見れば成功したか失敗したかどうか判別するWrapparが書けそうです。 他との整合性の都合
Perlで作っていたプログラムのCSVデータソートがあまりにも重い・・・
1万件ぐらいのソートをさせるとCPU全部喰らったあげく3秒ぐらい掛かります(苦笑) プログラムは下記のような感じでsort条件を関数化することで切り出してたのですが、さすがに限界を感じて別の方法を模索しました。 @sortedcsv = sort {&sortsplt(3
CPANを使ってperlのモジュールを追加しようと思ったのですがftp://ftp.kddlabs.co.jp/CPAN/につながらない模様。
っていうか、リトライしても全部同じところにつなぎに行っているっていうことは、kddlabs.co.jpしかCPANのURLリストに入ってないじゃん・・・_| ̄|○ なので、さっくりリストを追加してみました。 手
ちょっと特殊なデータを展開するために2000万ループほどするperlのプログラムを書いてみました。 実行したらP4 2.8GHzのマシンでおおよそ30秒・・・
この程度の速度ならいいんですが、そのプログラムを今後実行させるロートルなSunのマシンで走らせたら・・・630秒_| ̄|○ Cで書き直す決意をしました(笑) ちなみ
しょっちゅう忘れるのでメモ たとえば今日の元旦からの通算日をコマンドラインでぱっと求めるならこんな感じ
perl -e 'print "${[localtime(time)]}[7]\n"' 読み出したcsv形式の行をソートしてから配列に入れるならこんな感じ
$line = sort @{[split(/,/,$CSVline)]}
Dynamic DNSでDynDNSさんを用いていますが、こちら35日間更新がないとホスト名消されてしまうのがちょっと不便です。 そういうときWindowsだとDiCEなんかを使って自動更新しますが、私はLinuxから自動更新したかったので使ってません。 そこで、普通はddclientなんていうものを使うみたいですが、私の使い方とはこれともち