Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get description of an installed package without actual importing it

Tags:

python

If you type this:

import somemodule
help(somemodule)

it will print out paged package description. I would need to get the same description as a string but without importing this package to the current namespace. Is this possible? It surely is, because anything is possible in Python, but what is the most elegant/pythonic way of doing so?

Side note: by elegant way I mean without opening a separate process and capturing its stdout... ;)

In other words, is there a way to peek into a unimported but installed package and get its description? Maybe something with importlib.abc.InspectLoader? But I have no idea how to make it work the way I need.

UPDATE: I need not just not polluting the namespace but also do this without leaving any traces of itself or dependent modules in memory and in sys.modules etc. Like it was never really imported.

UPDATE: Before anyone asks me why I need it - I want to list all installed python packages with their description. But after this I do not want to have them imported in sys.modules nor occupying excessive space in memory because there can be a lots of them.

like image 280
V.K. Avatar asked Dec 31 '25 08:12

V.K.


1 Answers

The reason that you will need to import the module to get a help string is that in many cases, the help strings are actually generated in code. It would be pointlessly difficult to parse the text of such a package to get the string since you would then have to write a small Python interpreter to reconstruct the actual string.

That being said, there are ways of completely deleting a temporarily imported modules based on this answer, which summarizes a thread that appeared on the Python mailing list around 2003: http://web.archive.org/web/20080926094551/http://mail.python.org/pipermail/python-list/2003-December/241654.html. The methods described here will generally only work if the module is not referenced elsewhere. Otherwise the module will be unloaded in the sense that import will reload it from scratch instead of using the existing sys.modules entry, but the module will still live in memory.

Here is a function that does approximately what you want and even prints a warning if the module does not appear to have been unloaded. Unlike the solutions proposed in the linked answer, this function really handles all the side-effects of loading a module, including the fact that importing one package may import other external packages into sys.modules:

import sys, warnings
def get_help(module_name):
    modules_copy = sys.modules.copy()
    module = __import__(module_name)
    h = help(module)
    for modname in list(sys.modules):
        if modname not in modules_copy:
            del sys.modules[modname]
    if sys.getrefcount(module) > 1:
        warnings.warn('Module {} is likely not to be completely wiped'.format(module_name))
    del module
    return h

The reason that I make a list of the keys in the final loop is that it is inadvisable to modify a dictionary (or any other iterable) as you iterate through it. At least in Python 3, dict.keys() returns an iterable that is backed by the dictionary itself, not a frozen copy. I am not sure if h = ... and return h are even necessary, but in the worst case, h is just None.

like image 70
Mad Physicist Avatar answered Jan 01 '26 20:01

Mad Physicist