Monday, March 30, 2009

[perl] 修改 @INC 的几种方法

The @INC Array

@INC is a special Perl variable that is the equivalent to the shell's PATH variable. Whereas PATH contains a list of directories to search for executables, @INC contains a list of directories from which Perl modules and libraries can be loaded.

When you use(), require() or do() a filename or a module, Perl gets a list of directories from the @INC variable and searches them for the file it was requested to load. If the file that you want to load is not located in one of the listed directories, then you have to tell Perl where to find the file. You can either provide a path relative to one of the directories in @INC, or you can provide the full path to the file.

The %INC Hash

%INC is another special Perl variable that is used to cache the names of the files and the modules that were successfully loaded and compiled by use(), require() or do() statements. Before attempting to load a file or a module with use() or require(), Perl checks whether it's already in the %INC hash. If it's there, then the loading and therefore the compilation are not performed at all. Otherwise, the file is loaded into memory and an attempt is made to compile it. do() does unconditional loading -- no lookup in the %INC hash is made.

If the file is successfully loaded and compiled, then a new key-value pair is added to %INC. The key is the name of the file or module as it was passed to the one of the three functions we have just mentioned. If it was found in any of the @INC directories except ".", then the value is the full path to it in the file system.

The following examples will make it easier to understand the logic.

First, let's see what are the contents of @INC on my system:


% perl -e 'print join "\n", @INC'
/usr/lib/perl5/5.00503/i386-linux
/usr/lib/perl5/5.00503
/usr/lib/perl5/site_perl/5.005/i386-linux
/usr/lib/perl5/site_perl/5.005
.

Notice that . (current directory) is the last directory in the list.

Now let's load the module strict.pm and see the contents of %INC:


% perl -e 'use strict; print map {"$_ => $INC{$_}\n"} keys %INC'

strict.pm => /usr/lib/perl5/5.00503/strict.pm

Since strict.pm was found in /usr/lib/perl5/5.00503/ directory and /usr/lib/perl5/5.00503/ is a part of @INC, %INC includes the full path as the value for the key strict.pm.

Now let's create the simplest module in /tmp/test.pm:


test.pm
-------
1;

It does nothing, but returns a true value when loaded. Now let's load it in different ways:


% cd /tmp
% perl -e 'use test; print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => test.pm

Since the file was found relative to . (the current directory), the relative path is inserted as the value. If we alter @INC by adding /tmp to the end:


% cd /tmp
% perl -e 'BEGIN{push @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => test.pm

Here we still get the relative path, since the module was found first relative to ".". The directory /tmp was placed after . in the list. If we execute the same code from a different directory, then the "." directory won't match,


% cd /
% perl -e 'BEGIN{push @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => /tmp/test.pm

so we get the full path. We can also prepend the path with unshift(), so it will be used for matching before "." and therefore we will get the full path as well:


% cd /tmp
% perl -e 'BEGIN{unshift @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => /tmp/test.pm

The code:


BEGIN{unshift @INC, "/tmp"}

can be replaced with the more elegant:


use lib "/tmp";

Which is almost equivalent to our BEGIN block and is the recommended approach.

These approaches to modifying @INC can be labor intensive, since if you want to move the script around in the file-system, then you have to modify the path. This can be painful, for example, when you move your scripts from development to a production server.

There is a module called FindBin that solves this problem in the plain Perl world, but, unfortunately, it won't work under mod_perl, since it's a module, and as any module, it's loaded only once. So the first script using it will have all the settings correct, but the rest of the scripts will not if they're in a different directory from the first.

For the sake of completeness, I'll present this module anyway.

If you use this module, then you don't need to write a hard-coded path. The following snippet does all the work for you (the file is /tmp/load.pl):


load.pl
-------
#!/usr/bin/perl

use FindBin ();
use lib "$FindBin::Bin";
use test;
print "test.pm => $INC{'test.pm'}\n";

In the above example, $FindBin::Bin is equal to /tmp. If we move the script somewhere else... e.g. /tmp/x in the code above $FindBin::Bin equals /home/x.


% /tmp/load.pl

test.pm => /tmp/test.pm

This is just like use lib except that no hard-coded path is required.

You can use this workaround to make it work under mod_perl.


do 'FindBin.pm';
unshift @INC, "$FindBin::Bin";
require test;
#maybe test::import( ... ) here if need to import stuff

This has a slight overhead, because it will load from disk and recompile the FindBin module on each request. So it may not be worth it.



  1. -l /Users/xx/perl_lib
  2. BEGIN {
    push @INC,"/Users/xx/perl_lib";}
  3. export PERL5LIB=/Users/xx/perl_lib
  4. use lib "/Users/xx/perl_lib";

Thursday, March 19, 2009

gliffy 一个online 的流程图制作网站

http://www.gliffy.com/
一个提供在线制作流程图服务的网站,可在线绘制框图、流程图、网络拓补图等等,类似微软的visio,或者Mac上的OmniGraffle。在网上就可以绘制和保存,需要的时候也可以导出成SVG、JPEG或者PNG的格式,非常方便。Gliffy支持协同编辑,你可以通过email邀请你的好友共同编辑你的流程图

Wednesday, March 18, 2009

一个写文档的工具 sphinx

python 写的文档工具

官方网站:
http://sphinx.pocoo.org

tutorial:
http://scienceoss.com/use-sphinx-for-documentation/

Tuesday, March 17, 2009

google 大牛 Jeffery Dean 的在 WSDM 的报告

Google 大牛 Jeffery Dean ( http://research.google.com/people/jeff/) ,是map reduce 框架的发明者,
他在WSDM 09 的报告
Challenges in Building Large-Scale Information Retrieval Systems
透漏了一些google 内部实现细节,现在已经有了报告的 keynote,
英文版pdf 见 http://research.google.com/people/jeff/WSDM09-keynote.pdf
中文翻译见 http://docs.google.com/Present?docid=afdfdfhqkrd8_1098qht7ggj
另外还有 (http://glinden.blogspot.com/2009/02/jeff-dean-keynote-at-wsdm-2009.html) Greg的评论。

wsdm 09 的演讲视频 http://videolectures.net/wsdm09_barcelona/

有空可以看看