I have a perl module named Mysql_Routines that contains various functions I use for manipulating mysql data with DBI. I export these functions as follows:
package Mysql_Routines;
use DBI;
use strict;
use warnings;
use Data::Dumper;
use Exporter qw(import);
our #EXPORT_OK = qw(connect_to insert_row get_rows);
These are accessed from other scripts and modules using the following code:
use my_modules::Mysql_Routines qw (connect_to insert_row get_rows);
This would all appear to be standard practice, as documented on Perl Maven. However, I can only then call these functions by using the module identifier or I get an error that it's an undefined subroutine. For example:
my $dbh = Mysql_Routines::connect_to('./config/mysql-local.conf');
works.
my $dbh = connect_to('./config/mysql-local.conf');
throws the following error:
Undefined subroutine &main::connect_to called
It's obviously not a huge issue, although I'd like to understand why this is happening, as I appear to have followed the correct guidelines for creating modules containing functions.
Please see my solution below. The package declaration should have included the top directory. Silly mistake.
You seem to be confused about the name of your module. Is it "Mysql_Routines" or "my_modules::Mysql_Routines"? I suspect that you want it to be called "Mysql_Routines", in which case your use my_modules::Mysql_Routines is rather unusual. Wny wouldn't you just have use Mysql_Routines?
I guess the answer is that your module lives in a directory called "my_modules". In which case, the correct approach would be to add that directory to your library search path. You could use code like:
use lib 'my_modules';
use Mysql_Routines';
I've discovered that the problem is that in the package declaration of the module I didn't include the top directory.
Changing package Mysql_Routines to package my_modules::Mysql_Routines solves the problem. With this solution the library search path does not need to be updated as was suggested as an alternative.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have been scratching my head for about an hour for trying to get a .pm to work as a module for me.
My issue is quite simple.
The story:
I have made a package and used Moose for OOP.
I have saved the package, My::FileIO in the home directory under a common dir for all such custom modules in the form /home/USER/DIRECTORY/My/FileIO.pm. In fact, this was done after I used Module::Starter and used perl Makefile.PL which installed it in that format.
I used an external script to test the module. In that, I used use lib '/home/USER/DIRECTORY/' and then confirmed the presence of the module by checking %INC which yielded the correct filename value. This led me to conclude that perl had loaded the module without any complaints.
I tried to use this module by My::FileIO and the testing script had not complained at that time as well.
The testing script failed after I used the constructor in the Moose way, my $test = My::FileIO->new() and this is what it threw - Can't locate object method "new" via package "My::FileIO" (perhaps you forgot to load "My::FileIO"?) at line 1.
I tried to make a mock subroutine named init and it failed too.
The author of Perl Maven however succeeds using these codes (https://perlmaven.com/object-oriented-perl-using-moose)
His testing script
use strict;
use warnings;
use v5.10;
use Person;
my $teacher = Person->new( name => 'Joe' );
say $teacher->name;
His test module
package Person;
use Moose;
has 'name' => (is => 'rw');
1;
Summary:
The testing script is able to load the module successfuly.
I am not able to use the package at all.
This is the assumed FileIO.pm
package My::FileIO;
use feature 'state';
use List::Util qw(max);
use Data::Dumper;
use Moose;
use Type::Params qw(compile);
use Type::Utils;
use Types::Standard qw(Str FileHandle Int HashRef ArrayRef Maybe);
[ ALL THE CODE ]
1;
Full code is at https://pastebin.com/1kxiPazd
This is my testing file - test.pl
use lib '/home/USER/DIRECTORY';
use My::FileIO;
$test = My::FileIO->new() # Fails
What am I doing wrong? I made a mock module like Perl Maven's and tried testing it and it failed too.
Update -
I apologize for the silly errors in my writeup.
What you posted at the bottom will work assuming the full path of the file you called FileIO.pm is /home/USER/DIRECTORY/My/FileIO.pm.
The code you posted at the bottom is clearly not what you used in your test that gave error. The error message you provided said you used -e rather than using test.pl, and it said you tried to create an object of class My::Test rather than My::FileIO.
I need to write my own Test module (TestOwn) that use the Test::More module.
So the code of TestOwn.pm is something like:
package TestOwn;
use Test::More;
1;
Then i try to use the package in one of my test file (test01.t);
use lib -e 't' ? 't' : 'test';
use TestOwn;
....
done_testing();
But when the test is run i have the error:
t/test01.t .. Undefined subroutine &main::done_testing
So it seems that functions in Test::More are not imported in my test file by the use TestOwn command.
By default, nothing in your module is exported into the code that calls it. This is by design, as exporting is a rather dangerous activity that could result in name clashes.
You have to define what things to export by default (and you can also give the user of the module some control of this behavior). See Exporter.
You could export the methods of another module, but this isn't really a good idea. What if someone uses your module and Test::More? A better option would be to create your own wrappers around the Test::More functions that you think are needed, then export those. But you should limit exporting as much as possible. There are better alternatives, such as using an OO design with methods. See the above documentation for more discussion of this.
The calling code can also access stuff that is not exported by using Module::function().
I am getting this strange error when importing a module I wrote into my Dancer app.
Prototype mismatch: sub main::from_json: none vs ($#) at mymodule.pm line 6.
Prototype mismatch: sub main::to_json: none vs ($#) at mymodule.pm line 6.
I guess this is because in my module I'm importing the perl JSON module.
Everything seems to perform fine, but I'm wondering what this error/warning is all about? I can't seem to find anything about it online.
Another situation where this arises is when some other module you have loaded defines a from_json/to_json. An example I've hit a couple times recently is with Dancer. If you have a package with
package Foo;
use Dancer qw/:syntax/;
use JSON;
1;
You will get that warning because (apparently) Dancer with the :syntax import puts a from_json and to_json into your namespace.
A quick solution in this situation is to just explicitly import nothing from JSON:
package Foo;
use Dancer qw/:syntax/;
use JSON qw//;
1;
Then in your code you will need to use the full package name to get JSON's subs, like this:
my $hash = JSON::from_json('{"bob":"sally"}');
In a situation like this, though, you want to use the full package names so it's clear which function you're getting--there are multiple declarations of to_json/from_json, so let's be very clear which one we mean.
If you put the following in Foo.pm and run with "perl Foo.pm", with and without the qw// after the use JSON, you can see how it works:
package Foo;
use Dancer qw/:syntax/;
use JSON qw//;
print Dumper( JSON::from_json('{"bob":"sally"}') ); use Data::Dumper;
1;
I believe Dancer/2 provides to_json and from_json to you, so you don't have to use JSON.
This will work:
use Dancer2 ':syntax';
get '/cheeseburgers' => {
return to_json($restaurant->make_cheeseburgers);
}
The reason I was getting this error was because in my own module, I was using the use directive and importing JSON and other modules BEFORE I declared my own package namespace, with
package mymodule
instead of AFTER. The package declaration has to come first.
See Prototypes in perlsub. The functions from_json and to_json were defined with different prototypes than used in the code.
I have been USEing .pm files willy-nilly in my programs without really getting into using packages unless really needed. In essence, I would just have common routines in a .pm and they would become part of main when use'd (the .pm would have no package or Exporter or the like... just a bunch of routines).
However, I came across a situation the other day which I think I know what happened and why, but I was hoping to get some coaching from the experts here on best practices and how to resolve this. In essence, should packages be used always? Should I "do" files when I just want common routines absorbed into main (or the parent module/package)? Is Exporter really the way to handle all of this?
Here's example code of what I came across (I won't post the original code as it's thousands of lines... this is just the essence of the problem).
Pgm1.pl:
use PM1;
use PM2;
print "main\n";
&pm2sub1;
&pm1sub1;
PM1.pm:
package PM1;
require Exporter;
#ISA=qw(Exporter);
#EXPORT=qw(pm1sub1);
use Data::Dump 'dump';
use PM2;
&pm2sub1;
sub pm1sub1 {
print "pm1sub1 from caller ",dump(caller()),"\n";
&pm2sub1;
}
1;
PM2.pm:
use Data::Dump 'dump';
sub pm2sub1 {
print "pm2sub1 from caller ",dump(caller()),"\n";
}
1;
In essence, I'd been use'ing PM2.pm for some time with its &pm2sub1 subroutine. Then I wrote PM1.pm at some point and it needed PM2.pm's routines as well. However, in doing it like this, PM2.pm's modules got absorbed into PM2.pm's package and then Pgm1.pl couldn't do the same since PM2.pm had already been use'd.
This code will produce
Undefined subroutine &main::pm2sub1 called at E:\Scripts\PackageFun\Pgm1.pl line 4.
pm2sub1 from caller ("PM1", "PM1.pm", 7)
main
However, when I swap the use statements like so in Pgm1.pl
use PM2;
use PM1;
print "main\n";
&pm2sub1;
&pm1sub1;
... perl will allow PM2.pm's modules into main, but then not into PM1.pm's package:
Undefined subroutine &PM1::pm2sub1 called at PM1.pm line 7.
Compilation failed in require at E:\Scripts\PackageFun\Pgm1.pl line 2.
BEGIN failed--compilation aborted at E:\Scripts\PackageFun\Pgm1.pl line 2.
So, I think I can fix this by getting religious about packages and Exporter in all my modules. Trouble is, PM2.pm is already used in a great number of other programs, so it would be a ton of regression testing to make sure I didn't break anything.
Ideas?
See my answer to What is the difference between library files and modules?.
Only use require (and thus use) for modules (files with package, usually .pm). For "libraries" (files without package, usually .pl), use do.
Better yet, only use modules!
use will not load same file more than once. It will, however, call target package's import sub every time. You should format your PM2 as proper package, so use can find its import and export function to requestor's namespace from there.
(Or you could sneak your import function into proper package by fully qualifying its name, but don't do that.)
You're just asking for trouble arranging your code like this. Give each module a package name (namespace), then fully qualify calls to its functions, e.g. PM2::sub1() to call sub1 in package PM2. You are already naming the functions with the package name on them (pm2sub1); it is two extra characters (::) to do it the right way and then you don't need to bother with Exporter either.
I have a rather complex data structure I've implemented in Perl. This has been broken up into about 20 classes. Basically, any time you want to use one of these classes, you need to use all of them.
Right now, if someone wants to use this data structure, they need to do something like:
use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;
to be able to manipulate all parts of it. How can I write a module that does this for the user, so all they have to do is
use Component;
to get all of the other modules imported?
In this particular case, the modules are all classes and don't have exports.
If these are just classes (i.e. they don't export any functions or variables when you use them), then all that really matters is that they have been loaded.
Just create Component.pm:
package Component;
our $VERSION = '1.00';
use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;
1; # Package return value
You don't need Exporter or anything like it.
However, instead of having a module that is nothing but use statements, it probably makes more sense to put those use statements into the class of the root node, or into the module that creates the data structure. That is, people will want to say:
use Component::Root;
my $root = Component::Root->new(...);
or
use Component qw(build_structure);
my $root = build_structure(...);
depending on how your data structure is normally created. It might be a bit confusing for people to write:
use Component;
my $root = Component::Root->new(...);
but it really depends on what your API looks like. If there are a number of classes that people might be calling new on, then use Component might be the way to go.
You could use the export_to_level method for all those packages that are Exporters.
MyPackage->export_to_level($where_to_export, $package, #what_to_export);
You could also just export all the symbols you import.
use PackageA qw<Huey Dewey Louie>;
...
our #ISA = qw<Exporter>; #inherit Exporter
our #EXPORT = qw<Huey Dewey Louie>;
However, if you don't want to export any symbols, and just want to load modules, then just include those use statements above, and any package in the process will be able to instantiate them as classes, say if they were all OO modules.
Provided that they have been loaded successfully, they will exist in %INC and the symbol table.
Moose::Exporter seems to do this, although all your other modules will have to use it as well.
In Component:
Moose::Exporter->setup_import_methods(
also => [qw/Component::Root Component::..*/],
);
If the modules do not export anything and don't have an import method (same requirements as cjm's answer) you just need to load the modules without import:
package Component;
our $VERSION = '1.00';
require Component::Root;
require Component::Foo;
require Component::Bar;
require Component::Baz;
require Component::Flib;
require Component::Zen;
require Component::Zen::Foo;
require Component::Zen::Bar;
require Component::Zen::Baz;
... # 15 more of these...
require Component::Last;
1; # Package return value
The users of the module will just do:
require Component;
If however some modules do exports, you will have to call their import method. So you have add an import method in your Component module that will call them:
sub import
{
Component::Root->import;
Component::Foo->import;
...
}
and so the module users will have to use it:
use Component;
Note that you may have to use some other tricks if the imported module has to insert symbols in the importer's context. See for example how the POE's import does it.
The Modern::Perl module touts itself with “enable all of the features of Modern Perl with one command,” where that command is
use Modern::Perl;
and those features are
For now, this only enables the strict and warnings pragmas, as well as all of the features available in Perl 5.10. It also enables C3 method resolution order; see perldoc mro for an explanation.
That's a lot for one line of code, which according to the perlmod documentation is exactly equivalent to
BEGIN { require Module; import Module; }
Consider Modern::Perl's implementation:
package Modern::Perl;
our $VERSION = '1.03';
use 5.010_000;
use strict;
use warnings;
use mro ();
use feature ();
sub import {
warnings->import();
strict->import();
feature->import( ':5.10' );
mro::set_mro( scalar caller(), 'c3' );
}
1; # End of Modern::Perl
To adapt this to your situation, from your top-level module use all the other modules you want to load, and call their imports, if any, from MyTopLevelModule::import.
Note that you don't necessarily need to copy
use 5.010_000;
into MyTopLevelModule.pm, but that would be a fine idea! According to the use documentation:
In the peculiar use VERSION form, VERSION may be either a positive decimal fraction such as 5.006, which will be compared to $], or a v-string of the form v5.6.1, which will be compared to $^V (aka $PERL_VERSION). An exception is raised if VERSION is greater than the version of the current Perl interpreter; Perl will not attempt to parse the rest of the file. Compare with require, which can do a similar check at run time.