2009-11-03 42 views
32

Estoy en el proceso de codificación de una aplicación que tiene que obtener los metadatos (autor, versión ... etc) de varios módulos (archivos .py) y mostrarlos. El usuario selecciona un script y el script se ejecuta. (Se pueden agregar nuevos scripts y se pueden tomar los antiguos de la carpeta de destino como un sistema de complementos).Cómo des-importar un módulo de Python?

Primero importo un script y saco los metadatos, luego voy al siguiente. Pero quiero eliminar la importación de todos los demás módulos, excepto el que el usuario haya seleccionado.

¿Cómo puedo implementar esto?

he probado todas estas

1. del module 
2. del sys.modules['module'] 

Este último no funciona. Intenté con #python y obtuve la respuesta de que no era bueno desmantelar módulos, pero quiero conocer una forma clara de implementar esto. Cualquier idea/sugerencia ayudaría.

+7

No hay una forma clara de eliminar módulos. Todo lo que vas a hacer es a través de hacks. –

+0

Obtenga los metadatos analizando el código usando el módulo 'ast' en lugar de importarlos, como herramientas como [Epydoc] (http://epydoc.sf.net), [PyDoctor] (http://codespeak.net/~mwh/pydoctor /), y [Sphinx] (http://sphinx.pocoo.org) do. – Allen

Respuesta

18

Creo this post debería ayudarle a

edición: para asegurar la disponibilidad de esta información (en caso de que el enlace muere o algo similar) voy a incluir el mensaje original de la tutor mailing list aquí:


en 8/14/06, Dick Moores escribió:

en realidad, mi pregunta es, después de usar IDLE para hacer un poco de importación de módulos e inicialización de variables, cómo devolverlo a su condición inicial sin cerrarlo y volver a abrirlo.

Así, por ejemplo después de que he hecho

>>> import math, psyco 
>>> a = 4**23 

¿Cómo puedo eliminar los IDLE a cabo sin cerrar? (que solía conocer cómo, pero se me ha olvidado.)

Hola Dick,

lo general, esto implica la eliminación del "registro de módulo y la eliminación de referencias a él en el código. Si tiene un realmente módulo bien utilizado (como uno con parámetros de configuración importados en cada módulo), entonces tendrá un paso adicional de eliminarlo de cada módulo. Además, si tiene "uso de psico ... ", entonces no podrá liberar el módulo y la referencia al módulo e fácilmente (¿es de ese módulo o se importó de un tercer módulo? ver "si paranoide:. código de abajo)

Ésta función elimina un módulo por su nombre desde el intérprete de Python, el 'parámetro paranoica' es una lista de los nombres de las variables de eliminar de cualquier otro módulo de (supuestamente se va a eliminar con el módulo). Sea MUY cuidadoso con el parámetro paranoico , podría causar problemas para su intérprete si sus funciones y clases se llaman igual en diferentes módulos. Un evento común es "error" para las excepciones. las bibliotecas tienen una excepción de "catch-all" llamada "error" en el módulo.Si también denominó "error" a la excepción y decidió incluir eso en la lista de paranoicos ... hay que incluyen muchos otros objetos de excepción.

def delete_module(modname, paranoid=None): 
    from sys import modules 
    try: 
     thismod = modules[modname] 
    except KeyError: 
     raise ValueError(modname) 
    these_symbols = dir(thismod) 
    if paranoid: 
     try: 
      paranoid[:] # sequence support 
     except: 
      raise ValueError('must supply a finite list for paranoid') 
     else: 
      these_symbols = paranoid[:] 
    del modules[modname] 
    for mod in modules.values(): 
     try: 
      delattr(mod, modname) 
     except AttributeError: 
      pass 
     if paranoid: 
      for symbol in these_symbols: 
       if symbol[:2] == '__': # ignore special symbols 
        continue 
       try: 
        delattr(mod, symbol) 
       except AttributeError: 
        pass 

Entonces usted debe ser capaz de utilizar esto como:

delete_module('psyco') 

o

delete_module('psyco', ['Psycho', 'KillerError']) 
# only delete these symbols from every other module 
# (for "from psyco import Psycho, KillerError" statements) 

-Arcege

+3

¿Puede resumir los contenidos aquí si ese enlace alguna vez muere? –

+0

gracias por el enlace ... pero ¿hay alguna otra manera de obtener los metadatos que no sean la importación? – Sriram

+0

No existe un uso real para este código, nunca. – Allen

5

Sugerencia: Importar los módulos de forma dinámica utilizando __import__

P. ej.

module_list = ['os', 'decimal', 'random'] 
for module in module_list: 
    x = __import__(module) 
    print 'name: %s - module_obj: %s' % (x.__name__, x) 

producirá:

name: os - module_obj: <module 'os' from '/usr/lib64/python2.4/os.pyc'> 
name: decimal - module_obj: <module 'decimal' from '/usr/lib64/python2.4/decimal.pyc'> 
name: random - module_obj: <module 'random' from '/usr/lib64/python2.4/random.pyc'> 

Sin embargo, esto no será realmente quitarlo del registro módulos. La próxima vez que se importe, no volverá a leer el archivo del paquete/módulo y no lo ejecutará. Para lograr esto, sólo tiene que modificar el código anterior como esto:

import sys 
module_list = ['os', 'decimal', 'random', 'test1'] 
for module_name in module_list: 
    x = __import__(module_name) 
    print 'name: %s - module_obj: %s' % (x.__name__, x) 
    del x 
    sys.modules.pop(module_name) 
2

Sé que este post ha sido fuera de fecha pero acabo encontrado con este tema y se lucha contra ella en los últimos días. Ahora llegué con una conclusión que puede resolver perfectamente este problema. Por favor, vea el código de ejemplo siguiente:

try: 
    theMod = sys.modules['ModNeedToBeDel'] 
except: 
    theMod = None 
if theMod: 
    del sys.modules['ModNeedToBeDel'] 

#The extra try/except below is because I implemented the block in a module of a sub-package; this ModNeedToBeDel in my case was imported either by the toppest level Main code, or by the other sub-package modules. That's why I need two different try/except. 

try: 
    theMod = sys.modules['UpperFolder.ModNeedToBeDel'] 
except: 
    theMod = None 
if theMod: 
    del sys.modules['UpperFolder.ModNeedToBeDel'] 
import ModNeedToBeDel # or UpperFolder.ModNeedToBeDel here 

Tenga en cuenta que del sys.modules[theMod] no funcionará, ya que sólo elimina la referencia, en lugar de la actual ModNeedToBeDel.

Espero que esto pueda ayudar a alguien para que no tenga que luchar en este tema durante varios días.