42

I am in the process of coding an app which has to get the metadata (author,version..etc) out of several modules (.py files) and display them. The user selects a script and the script is executed. (New scripts can be added and old ones be taken of from the target folder just like a plugin system).

Firstly I import a script and I take out the metadata, then I go for the next. But I want to de-import all the other modules except for the one that the user has selected.

How can I implement this?

I tried these

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

The latter did not work. I tried #python and got the answer that it was not good to de-import modules, but I want to know a clean way of implementing this. Any ideas/suggestions would help.

Dana
  • 32,083
  • 17
  • 62
  • 73
Sriram
  • 1,180
  • 2
  • 15
  • 27
  • 8
    There _is_ no clean way to deimport modules. Everything you're going to do is through hacks. – Georg Schölly Nov 03 '09 at 16:08
  • Get metadata by parsing the code using the `ast` module instead of importing them, as tools like [Epydoc](http://epydoc.sf.net), [PyDoctor](http://codespeak.net/~mwh/pydoctor/), and [Sphinx](http://sphinx.pocoo.org) do. – Allen Apr 01 '11 at 21:45

4 Answers4

22

i think this post should help you

edit: to secure the availability of this information (in case the link dies or something similar) i will include the original message from the tutor mailing list here:


On 8/14/06, Dick Moores wrote:

Actually, my question is, after using IDLE to do some importing of modules and initializing of variables, how to return it to it's initial condition without closing and reopening it.

So, for example after I've done

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

How can I wipe those out without closing IDLE? (I used to know how, but I've forgotten.)

Hi Dick,

Usually this entails removing from the "module registry and removing references to it in the code. If you have a really well used module (like one with config parameters imported into every module), then you'll have an additional step of removing it from every module. Also, if you have use "from psyco import ...", then you will not be able to free up the module and the reference to the module easily (is it from that module, or imported from a third module? see "if paranoid: code below).

The function below deletes a module by name from the Python interpreter, the "paranoid" parameter is a list of variable names to remove from every other module (supposedly being deleted with the module). Be VERY careful with the paranoid param; it could cause problems for your interpreter if your functions and classes are named the same in different modules. One common occurrance of this is "error" for exceptions. A lot of libraries have one "catch-all" exception called "error" in the module. If you also named your exception "error" and decided to include that in the paranoid list... there go a lot of other exception objects.

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

Then you should be able to use this like:

delete_module('psyco')

or

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

-Arcege

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
gabtub
  • 1,460
  • 2
  • 18
  • 21
7

Suggestion: Import your modules dynamically using __import__

E.g.

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

Will produce:

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'>

Though, this won't really remove it from the modules registry. The next time that it is imported, it won't re-read the package/module file and it won't execute it. To accomplish that, you can simply modify the above code snippet like this:

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)
Ehsan Foroughi
  • 3,010
  • 2
  • 18
  • 20
7

I recently found this post https://www.geeksforgeeks.org/reloading-modules-python/ and so for Python 3.4 or later use

import importlib
importlib.reload(module) 
2

I know this post has been out of date but I just encountered this issue and was struggling against it for the past few days. Now I came with a conclusion that can perfectly solve this issue. Please see the sample code below:

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

Note that del sys.modules[theMod] won't work, because it just deletes the reference, instead of the actual ModNeedToBeDel.

Hope this could help someone so that they won't have to struggle on this issue for several days!

Marko
  • 20,385
  • 13
  • 48
  • 64
LittleDong
  • 21
  • 1