简体   繁体   中英

Something wrong with @INC in perl?

Let's imagine we are new to perl and wrote some great module MyModule.pm . We also wrote some great script myscript.pl , that need to use this module.

use strict;
use warnings;
use MyModule;
etc...

Now we will create dir /home/user/GreatScript and put our files in it. And trying to run myscript.pl ...

cd /home/user/GreatScript
perl myscript.pl

Great! Now moving to another dir...

cd /
perl /home/user/GreatScript/myscript.pl

Getting some not very usefull error about @INC and list of paths. What is this? Now after some googling we know that @INC contains paths where to search our modules, and this error means that Perl can't find out MyModule.pm.

Now we can:

  • Add path to system PERL5LIB var, it will add our path to the beginning of @INC Install our module to one of dirs from @INC
  • Manually add our path to @INC in the BEGIN section Add use lib '/home/user/GreatScript'; to our script, but it looks bad. What if we will move our script to other dir?
  • Or use FindBin module to find our current dir, and use this path in use lib "$FindBin::Bin"; , but it's not 100% effective, for example some bugs with mod_perl or issues ...
  • Or use __FILE__ (or $0) variable and extract path from it using abs_path method from Cwd module. Looks like a yet another bicycle?
  • Or some forgotten or missing ( Did I miss something? )

If I have one script, it's easy... But why I need to write this few additional lines of code to all my scripts? And it will not work 100%! Why perl not adding current script dir to @INC by default, like it does with "."?

PS: I was searching for answer to my question but find only list of solutions from the list above and some others. I hope this question is duplicate...

Or some forgotten or missing ( Did I miss something? )

Another option: Don't keep your module with your script . The module is separate because it is re-usable, so put it in a library folder. This can be anything from a local library for personal projects, included with use lib (and perhaps referencing an environment variable you have set up for the project), to making the module into a CPAN library, and letting cpan manage where it goes. What you decide to do depends on how re-usable your code is, beyond how the script uses it.

Why this obvious and regular operation need a lot of work?

It is not a lot of work in the scheme of things. Your expectation that files grouped together in the file system, should automatically be used by Perl at the language level to resolve require or use statements is not true. It's not that it is impossible, or that your expectation is unreasonable, just that Perl is not implemented that way. Changing it after the fact could affect how many existing projects work, and may be contentious - so is unlikely to change.

If your use case is: "I want to have a script which accesses additional modules or other resources in the same or relative directory, and I don't want to install everything", then FindBin is a perfect solution. The limitation mentioned in the manpage happens only in persistent environments like mod_perl, but here I would propose different solutions (eg using FindBin only within httpd.conf, not in the scripts/modules).

(/me is a heavy FindBin user, and I am also the author of half of the KNOWN ISSUES section of the FindBin manpage)

That is need in order to know which module would you like to use. When you move to another catalog as you said perl looks in '.' catalog so if run:

cd /
perl /home/user/GreatScript/myscript.pl

and if MyModule.pm in '/' perl will find it and will be use in myscrpit.pl . Now as Perl finds module in the @INC in order which catologs in it you have to keep an eye on @INC.

Summary: obvious and regular operation is need to prevent using wrong module with the same name what you want to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM