Perl-Subrutina redefinida
subroutine (9)
¿Estás por casualidad ejecutando esto como un script cgi en un servidor web?
Creo que necesito reiniciar el servidor web para evitar esta advertencia.
He hecho esta pregunta antes o buscado y he visto a otros preguntar: ¿por qué recibo la advertencia " Subrutina mySub redefinida en ../lib/Common.pm línea x "? y siempre obtienes la respuesta que declaraste el subtítulo dos veces en el mismo código . Creé este paquete de prueba:
ARCHIVO COMPLETO ---------------
package MyCommonPkg;
use strict;
sub thisSubroutineIsNotDefinedAnywhereElse{
}
1;
ARCHIVO COMPLETO ---------------
y UTILIZO este paquete desde una secuencia de comandos de perl, que usa otros paquetes, que también usan este paquete, y recibo la advertencia:
Subrutina ThisSubroutineIsNotDefinedAnywhereElse redefinido en ../lib/MyCommonPkg.pm línea 19.
Prometo que no declare este submarino en ningún otro lado. Entonces, ¿esto es causado por una referencia circular? ¿Cómo puedo seguir la causa de esta advertencia y corregirla?
¿Tienes un bucle de dependencia? Si Perl comienza a compilar su script y encuentra una línea como esta:
use PackageA;
Perl pausa la compilación de tu script; localiza PackageA.pm y comienza a compilarlo. Si encuentra una línea como esta:
use PackageB;
Perl pausa la compilación de PackageA; localiza PackageB.pm y comienza a compilarlo. Normalmente, eso se completaría con éxito, y Perl volvería a completar la compilación de PackageA y, cuando se complete con éxito, volvería a compilar su script y, cuando se complete con éxito, comenzaría a ejecutar los códigos de operación compilados.
Sin embargo , si PackageB.pm contiene esta línea:
use PackageA;
Es posible que no haga nada, ya que Perl ya procesó PackageA.pm, pero el problema es que aún no ha terminado. Así que Perl hará una pausa en la compilación de PackageB y comenzará a compilar PackageA.pm nuevamente desde el principio. Eso podría provocar que se redefina el mensaje que está viendo sobre las subrutinas en PackageA.
Como regla general, dos paquetes no deberían depender el uno del otro. A veces, sin embargo, el bucle es más difícil de localizar porque es causado por un tercer paquete.
Asegúrate de no haber olvidado esta línea al final de tu módulo:
1;
Sé que se ha incluido en algunos de los ejemplos aquí, pero lo menciono porque es fácil de pasar por alto, y en mi caso resultó ser la única causa de los errores.
Cuando tiene dos subrutinas con el mismo nombre en diferentes paquetes, debe ver esta advertencia (cuando las advertencias están habilitadas) como "Subrutina nueva redefinida ...". La razón simple (que está muy cerca de lo que dijo Grant McLean, pero aún no exactamente) es que debes obtener tus paquetes omitiendo la fase de compilación y luego hacer que se requiera. De esta forma, el administrador del espacio de nombres de Perl no encontrará ningún símbolo conflictivo con el mismo nombre en el momento de la compilación, y si los módulos no tienen ningún error, también funcionarán correctamente.
Solo asegúrate de implementar
requiere el Módulo;
declaración en lugar de
usar el Módulo;
No deberías volver a ver esta advertencia.
Eche un vistazo al package MyCommonPkg.pm
del programa package MyCommonPkg.pm
y vea lo que dice. ¿Tiene algo como esto?
package MyCommonPkg;
use Exporter qw(import); # Might be "require" and not "use"
our @EXPORT = qw(thisSubroutineIsNotDefinedAnywhereElse);
La sintaxis puede ser un poco diferente. Lo principal que debería ver es la declaración del package
, que está usando Exporter
y que la matriz @EXPORT
tiene el nombre de su subrutina.
Lo que está pasando es un choque de espacio de nombres. Su paquete está definiendo la misma subrutina que está definiendo.
Para evitar que esto suceda, Perl usa espacios de nombres . Por defecto, su espacio de nombres es main
. Sin embargo, se supone que los paquetes deben definir sus propios homónimos usando el comando package
.
El espacio de nombre completo de una subrutina o variable es el espacio de nombres seguido de dos puntos dobles, seguido de la subrutina o el nombre de la variable. Por ejemplo, si mira File::Find , verá referencias a las variables $File::Find::name
y $File::Find::dir
. Estas son las variables $name
y $dir
dentro del paquete File/Find.pm
en el espacio de nombres File::Find
.
Para facilitarle las cosas, los paquetes pueden exportar sus variables y subrutinas a su espacio de nombres principal . Por ejemplo, si uso File::Copy , O puede hacer esto:
...
use File::Copy
...
copy ($file, $to_dir);
En lugar de:
...
use File::Copy
...
File::Copy::copy ($file, $to_dir);
Si miras File/Copy.pm
, verás lo siguiente:
package File::Copy;
...
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
...
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(copy move);
El package File::Copy;
define un espacio de nombre. El require Exporter;
y @ISA = qw(Exporter)
permite que el paquete exporte subrutinas y variables en el espacio de nombres principal . El @EXPORT
automáticamente, sin que le diga nada, importa la copy
y move
subrutinas al espacio de nombres principal, ¡ lo quieran o no!
Eso último es muy importante. Ahora se considera de mala educación usar @EXPORT
. En su lugar, debe usar @EXPORT_OK
que requiere que liste las subrutinas que desea usar. Paquetes más modernos como Scalar::Util hacen esto.
Entonces varias cosas Primero, ¿su MyCommonPkg
tiene un package MyCommonPkg;
declaración. Si no, debería. Esto evita que las subrutinas y las variables de los paquetes afecten su programa de maneras desagradables. Luego, puede usar @EXPORT
o @EXPORT_OK
.
Si MyCommonPkg
tiene una declaración de package
, ¿usa @EXPORT
? Si es así, tienes varias formas de evitar este problema:
- Ignora la advertencia. Es solo una advertencia. Como sabe que está redefiniendo la subrutina y desea usar su definición de la subrutina, ignórela.
Puede hacer esto para desactivar la advertencia a medida que redefina la subrutina:
use MyCommonPkg;
no warnings qw(redefine);
sub thisSubroutineIsNotDefinedAnywhereElse {
...
}
use warnings qw(redefine);
- El uso
require MyCommonPkg;
en lugar deuse MyCommonPkg;
. Esto evitará la importación de cualquier subrutina o variable en su espacio de nombres, incluidas las que desea utilizar. Digamos queMyCommonPkg
define cuatro subrutinas:thisSubroutineIsNotDefinedAnywhereElse
,foo
,bar
ybarfoo
. Para usar cualquiera de estas subrutinas.
Usted necesita hacer ésto:
my $answer = MyCommonPkg::foo( $input );
No es divertido.
Use otro nombre para su subrutina. Debería haberse documentado que esta subrutina se define en
MyCommonPkg
, y si desea usarMyCommonPkg
, no debe usar nombres de subrutinas que se exportan.Finalmente, si
MyCommonPkg
es bastante nuevo y no se usa en docenas de programas, use@EXPORT_OK
lugar de@EXPORT
, y asegúrese de que todos los programas que usanMyCommonPkg
se modifiquen para exportar las subrutinas que desean:
Me gusta esto:
use MyCommonPkg qw(foo bar);
En este caso, solo se exportan las subrutinas foo
y la bar
. Las subrutinas thisSubroutineIsNotDefinedAnywhereElse
y barfoo
no se exportan a su entorno.
Esto suena como un problema causado por dependencias circulares. Aquí es cómo rastrearlo. Si su clase de problema se ve así:
package AlientPlanet;
use Dinosaurs;
sub has_dinosaurs {...}
1;
Luego cambie su ejemplo para que se vea así:
package AlienPlanet;
sub has_dinosaurs {...} # <-- swap
use Dinosaurs; # <-- swap
1;
Ahora compila tu código con Carp :: Siempre así:
⚡ perl -MCarp::Always -c lib/AlienPlanet.pm
Subroutine has_dinosaurs redefined at lib/AlienPlanet.pm line 4.
require AlienPlanet.pm called at lib/Dinosaurs.pm line 4
Dinosaurs::BEGIN() called at lib/AlienPlanet.pm line 4
eval {...} called at lib/AlienPlanet.pm line 4
require Dinosaurs.pm called at lib/AlienPlanet.pm line 5
AlienPlanet::BEGIN() called at lib/AlienPlanet.pm line 4
eval {...} called at lib/AlienPlanet.pm line 4
lib/AlienPlanet.pm syntax OK
Ahora que tienes una stacktrace puedes ver dónde está el bucle. La solución rápida y sucia es usar Class :: Load en Dinosaurs.pm.
Para una explicación más detallada, prueba mi publicación en el blog .
Si está en un sistema con un sistema de archivos insensible a mayúsculas y minúsculas (Windows, y muy a menudo OSX), y use Common
en un archivo y use common
en otro, puede causar problemas como este.
Traté de usar el "paquete Common.pm" como nombre de paquete. El compilador me dio errores. Muy amable, ¿eh? ¿Qué versión de Perl estás usando? Lo intenté en 5.10.0 y 5.12.1.
Incluso si puede compilar, es una buena práctica eliminar el archivo .pm. Por ejemplo;
Archivo: some_package.pm;
package some_package;
use strict;
sub yadayadayada { ... }
1;
Yo tuve el mismo problema; Fue porque el programa usaba un módulo y la subrutina estaba presente tanto en el programa como en el módulo perl;