Inconveniente usando 'global' dentro de 'exec'

Sebastián Lezica slezica en fibertel.com.ar
Jue Abr 15 18:47:34 CEST 2004


Hola gente!,
	Ante todo mucho gusto, mas alla de llevar ya un tiempo leyendo la lista, nunca habia escrito en
ella.
	Estoy haciendo mis primeros pinitos en Python, y me encuentro trabado; intento hacer una aplicación
sobre Python 2.3.3 que:

1. Lea dinámicamente los módulos 'aa_xxxxx' que se encuentren en su directorio al iniciarse.
2. Asigne a estos modulos, un nombre sin el 'aa_' inicial, también globalmente.
3. Mantenga una lista (PLUGINS) que contiene a)Nombre por el cual puede accederse al modulo,
b)Nombre del fichero, y c)Fecha de ultima modificación del mismo.
4. Antes de ejecutar una función en uno de estos módulos, verificar si la variable 'HOT_RELOAD' es
verdadera y si la fecha de ultima modificacion del fichero es diferente a la almacenada en PLUGINS;
si es asi, volver a recargar el modulo modificado y actualizar la lista PLUGINS.

Mi problema:
	Si pongo en el exec la sentencia 'global ...' al comienzo, me da un error.
	Si la pongo luego del 'if', me da la advertencia '<string>:0: SyntaxWarning: name 'ibero' is used
prior to global declaration' (pero funciona).
	Si no la pongo, por supuesto el modulo se recarga pero veo los cambios en la primera vuelta, al
volver al timer se recupera el objeto 'antiguo' que era global...

	Bueno, agradeceré cualquier tipo de comentarios, tanto si hay una manera mas prolija o 'correcta'
de hacer esto mismo, como de pistas para encontrar en que estoy equivocandome (y disculpas
anticipadas si estoy preguntando una tonteria...). A continuación pongo un código que simula mi
error, y fragmentos del código original.

	Muchas gracias!.

Sebastián Lezica

Codigo breve para mostrar mi fallo (el modulo aa_ibero.py que se hace referencia esta al final del
email):
#-------------------------
import os
import aa_ibero
ibero = aa_ibero.asi()
PLUGINS=[['ibero', 'aa_ibero.pyc', 1081997928]]
for plugin in PLUGINS:
    #Esta linea da el error:
    exec('global %s; if %s.HOT_RELOAD == True and os.lstat(\'%s\')[-2] <> %d: print \'Recargando
%s...\'; PLUGINS[%d][2] = os.lstat(\'%s\')[-2]; reload(aa_%s); %s = aa_%s.asi()' %
          (plugin[0], plugin[0],                           plugin[1],plugin[2],          plugin[0],
PLUGINS.index(plugin),   plugin[1],     plugin[0], plugin[0],plugin[0]))
    #Esta linea no tiene el global inicial y no da error:
    #exec('if %s.HOT_RELOAD == True and os.lstat(\'%s\')[-2] <> %d: print \'Recargando %s...\';
PLUGINS[%d][2] = os.lstat(\'%s\')[-2]; reload(aa_%s); %s = aa_%s.asi()' %
          (plugin[0],                           plugin[1],plugin[2],          plugin[0],
PLUGINS.index(plugin),   plugin[1],     plugin[0], plugin[0],plugin[0]))
#-------------------------



Fragmentos del codigo real (a título anecdotico):

Al inicio del código hago lo siguiente:
#-------------------------
global PLUGINS
PLUGINS = []
for file in os.listdir('.'):
    if file[:3] == 'aa_':
        #Plugin disponible; creo una variable global y lo cargo:
        if not (file[3:file.find('.')] in `PLUGINS`):
            exec('global %s' % (file[3:file.find('.')]))
            exec('import %s' % (file[:file.find('.')]))
            exec('%s = %s.asi()' % (file[3:file.find('.')], file[:file.find('.')]))
            PLUGINS.append([file[3:file.find('.')], file, os.lstat('./%s' % (file))[-2]])
#-------------------------

En un timer (con wxPython) cada 10 segundos:
#-------------------------
            for plugin in PLUGINS:
                exec('if %s.HOT_RELOAD == True and os.lstat(\'%s\')[-2] <> %d: print \'Recargando
%s...\'; PLUGINS[%d][2] = os.lstat(\'%s\')[-2]; reload(aa_%s); %s = aa_%s.asi()' %
                     (plugin[0],                           plugin[1],plugin[2],          plugin[0],
PLUGINS.index(plugin),       plugin[1],     plugin[0],plugin[0],plugin[0]))
                exec('Response = %s.%s(locals)' % (plugin[0], 'TimerEvent'))
#-------------------------

Un módulo se forma asi (por ejemplo llamado 'aa_ibero.py'):
#-------------------------
import time
class asi:
    HOT_RELOAD = True
    def __init__(self):
        self.CONTADOR = 0
    def TimerEvent(self, req_locals):
        self.CONTADOR += 10
        print 'IBERO %d/%s' % (self.CONTADOR, time.time())
        return(True)
#-------------------------




Más información sobre la lista de distribución Python-es