Python - Acceso a funciones desde paquetes y modulos diferentes

   
Vista:

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio afulloa@uvigo.es (6 intervenciones) el 15/06/2015 18:04:15
El problema lo he resumido en dos programas de dos módulos "mcero.py" y "muno.py" que contiene la superclase "ccero" y subclase "cuno (ccero):" respectivamente con la estructura de paquetes siguiente:

1
2
3
4
cero/
.      .  mcero.py
       + uno/
.                 . muno.py

El problema surge cuando "cuno" llama a una función " f01" dentro del paquete muno.py a través de un método de la superclase ccero.fex() que ejecuta un "exec" para ejecutar " f01("cadena..") " que realizar un print, como se puede ver en el código, dando el error:

NameError: name 'f01' is not defined

Entiendo que la función 'f01' al estar en el paquete "muno.py" no es vista por la función de la superclase "ccero.fex()" del paquete mcero.py.

Mi problema consiste en como puedo resolver este problema de visibilidad de una función de la superclase que deba ver una función o clase dentro del paquete de la subclase, ya que estoy desarrollando una aplicación que se repite este problema en los diferentes paquetes, y no me interesa fusionar todo el código en uno solo para solventarlo.

Les dejo el código para que puedan ayudarme a resolverlo.

También es interesante que me puedan decir donde puedo leer algo sobre la integración de paquetes para no repetir este problema o similar.

Gracias.

Módulo mcero.py en paquete "cero"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def f0(var=""):
    print "       function f0() arg ->",var
"""
def f01(var=""):
    print "     function f01() arg-> ", var
"""
class ccero(object):
    def __init__(self,argv=''):
        self.argv = argv
        self.name = "cero"
        self.expresion= "f0(' class "+ self.name + "')"
 
    def info(self):
        print '\n','*'*25
        print ' class ccero.info() ->', self.name
        print '   expresion class ccero.fex("'+ self.expresion+'")'
        self.fex(self.expresion)
 
    def fex(self, expresion):
        exec(expresion)
 
if __name__=='__main__':
    f=ccero('teste')
    f.info()



Módulo muno.py en paquete "uno"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import sys
sys.path.append('.../prg')
 
from cero.mcero import *
 
# function test form inner muno.py called from function cero.fex
def f01(var=""):
    print "\n    function f01() arg-> ", var
 
# new subclass "uno" from super "cero"
class cuno(ccero):
    def __init__(self, argv=''):
        ccero.__init__(self, argv)
        self.name = "uno"
    def infob(self):
        print '**  infob() from  class uno  ***', '\n'
        self.expresion= "f0(' from class "+ self.name + "')"
        self.info()
        self.expresion= "f01(' from class "+ self.name + "')"
        print ' calling cuno.fex(' + self.expresion + ')'
        self.fex(self.expresion)
 
if __name__=='__main__':
    cu=cuno('teste')
    cu.infob()


les dejo el archivo rar con el código.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de xve

Acceso a funciones desde paquetes y modulos diferentes

Publicado por xve (1237 intervenciones) el 15/06/2015 19:30:16
Hola Antonio, vaya lio de nombres y archivos...

he intentado averiguar cual es tu problema, pero no me aclaro...

olvidándonos de tu código, lo que quieres es instanciar un archivo que se encuentra en una carpeta inferior u otra carpeta diferente a tu archivo python?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio (6 intervenciones) el 15/06/2015 20:17:50
Gracias por contestar, la verdad que esto es "inmediato".

Bien si es eso exactamente, es decir, trato de instanciar desde una subclase que se encuentra en un modulo X inferior donde están todas las clases que quiero instanciar, y trato de instanciarlas a través de la función contenida en la superclase que se encuentra en otro modulo y paquete superior.
La función llamada, en el ejemplo " fex() " de la superclase, no encuentra la función "f01" al no estar en el mismo modulo.
esto me da el error descrito de que no encuentra la función, o clase en el programa original.

he tratado de cruzar los imports en los dos módulo y me da un error, con lo que no consigo una solución adecuada, ya que las clases en el trabajo original son recurrentes y se encajan unas con otras, y la clase base es común para a aplicación, puedo hacer una chapuza para que funcione si la clase base la pongo en todos los módulos, pero esto es una chapuza como digo y no es buena para mantener.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve

Acceso a funciones desde paquetes y modulos diferentes

Publicado por xve (1237 intervenciones) el 16/06/2015 07:14:53
Hola Antonio, para ello, la manera que yo utilizo, es añadir la ruta al sys.path...

1
sys.path.append("/ruta/absoluta/")

De esta manera podrás instanciar cualquier archivo que se encuentra en dicha carpeta.

Si muestras el contenido de sys.path, veras todas las rutas que utiliza.

Coméntanos si te sirve, ok?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio (6 intervenciones) el 16/06/2015 09:08:19
Lo que me comentas ya esta hecho, y agrego al sys.path a las rutas del PYTHONPATH, pero sigue dando error como se puede ver en el código.
Si se ejecuta desde la terminal mcero.py da lo siguiente (la carpeta del paquete cero y su contenido están en el escritorio):

usr@host:~/Escritorio$ python cero/mcero.py

*************************
1
2
3
class ccero.info() -> cero
   expresion class ccero.fex("f0(' class cero')")
       function f0() arg ->  class cero

Salida correcta ya que 'f0()' esta en el módulo "mcero.py" como se puede ver en el código del enunicado.
Si ejecuto muno.py, en la carpeta/paquete cero/uno/muno.py, la salida da el error dado que la superclase en "mcero.py" no ve la función 'f01()' en el modulo 'muno.py' del paquete "uno" agua abajo de "cero:

antonio@papa:~/Escritorio$ python cero/mcero.py

*************************
1
2
3
4
5
class ccero.info() -> cero
   expresion class ccero.fex("f0(' class cero')")
       function f0() arg ->  class cero
antonio@papa:~/Escritorio$ python cero/uno/muno.py
**  infob() from  class uno  ***


*************************
class ccero.info() -> uno
expresion class ccero.fex("f0(' from class uno')")
function f0() arg -> from class uno
calling cuno.fex(f01(' from class uno'))
Traceback (most recent call last):
File "cero/uno/muno.py", line 26, in <module>
cu.infob()
File "cero/uno/muno.py", line 22, in infob
self.fex(self.expresion)
File "/home/antonio/Escritorio/cero/mcero.py", line 21, in fex
exec(expresion)
File "<string>", line 1, in <module>
NameError: name 'f01' is not defined

Se puede observar que el acceso a las funciones del paquete "cero" del módulo de la superclase "ccero" de la subclase "cuno" es correcta " function f0() arg -> class cero", pero el método de la superclase "fex()" falla , tal como se lee del error reportado.
En resumen la superclase no accede a las funciones o clases del modulo 'cuno.py' del paquete 'cero.uno' a pesar de ser ejecutado en este módulo, como si la superclase de lo único que se entera es de todo lo que contine el módulo donde esta definida.
Realizar un import cruzado de 'muno.py' (from cero.uno.mcero import * ) en mcero y mcero sobre muno me dío error, puede ser algo que se me escapa o ¿que no se puede?

La pregunta sigue siendo ¿como se pude dar visibilidad del contenido de las clases o funciones al módulo superior y por tanto a la superclase para que reconozca las clases del módulo inferior?

Bueno no sé si me he aclarado bien con esta última aclaración..

Gracias una vez más por vuestra ayuda.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve

Acceso a funciones desde paquetes y modulos diferentes

Publicado por xve (1237 intervenciones) el 16/06/2015 15:59:22
Hola Antonio, ahora me doy cuenta, de que has puesto tres puntos... y tienen que ser dos...
1
sys.path.append('.../prg')

Puede ser ese el problema?

Si no es ese el problema, prueba a poner la ruta absoluta.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio (6 intervenciones) el 16/06/2015 17:15:18
la ruta
sys.path.append('.../prg')

es correcta, esta omitida para quien la descargue los fuentes la ajuste a la ruta donde están los paquetes. Y te puedo asegurar que esto funciona bien. Puedes comprobarlo en la salida del post anterior que no da ningún error de búsqueda.

Como os he comentado, es un problema de visibilidad de funciones en paquetes externos, y el tema es como se puede hacer visibles funciones o clases hijas en paquetes diferentes a la superclase...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve

Acceso a funciones desde paquetes y modulos diferentes

Publicado por xve (1237 intervenciones) el 16/06/2015 18:45:45
Hola Antonio, yo he modificado tu archivo muno.py, con mi path... he puesto esto:
1
sys.path.append("/home/xve/test/")
Dentro de la carpeta test esta la carpeta cero

Si ejecuto:
1
python cero/uno/muno.py
me devuelve:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
**  infob() from  class uno  ***
 
 
*************************
 class ccero.info() -> uno
   expresion class ccero.fex("f0(' from class uno')")
       function f0() arg ->  from class uno
 calling cuno.fex(f01(' from class uno'))
Traceback (most recent call last):
  File "cero/uno/muno.py", line 26, in <module>
    cu.infob()
  File "cero/uno/muno.py", line 22, in infob
    self.fex(self.expresion)
  File "/home/xavi/www/test/cero/mcero.py", line 21, in fex
    exec(expresion)
  File "<string>", line 1, in <module>
NameError: name 'f01' is not defined
Que es correcto, porque no puede llamar a la funcion f01() del archivo muno,py desde el modulo fex() del archivo mcero.py

Si te fijas, no me aparece el error que te aparece a ti.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio (6 intervenciones) el 16/06/2015 21:49:03
Es correcto te da el mismo error que a mi,

NameError: name 'f01' is not defined

la superclase no ve la función 'f01()'. Ese es el error que quiero corregir.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve

Acceso a funciones desde paquetes y modulos diferentes

Publicado por xve (1237 intervenciones) el 17/06/2015 08:28:58
Hola Antonio, es que no lo va a poder ejecutar, ya que quien lo ejecuta no lo ha instanciado...

muno instancia mcero
mcero no puede ejecutar funciones de muno a no ser que la instancie!!!

Igual te pasaría desde muno si no instancias a mcero.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Acceso a funciones desde paquetes y modulos diferentes

Publicado por Antonio (6 intervenciones) el 17/06/2015 08:53:49
¿Como arreglo entonces el codigo?¿En donde la instancio (me imagino que delante)?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar