7

I know that if I import a module by name import(moduleName), then I can reload it with reload(moduleName)

But, I am importing a bunch of modules with a Kleene star:

from proj import *

How can I reload them in this case?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Anas Elghafari
  • 1,062
  • 1
  • 10
  • 20
  • 9
    That's one more reason not to use starred imports. – vaultah Jul 21 '14 at 11:18
  • Maybe you can try with sys module itself. Listing all modules loaded (sys.moduled.keys() ) and executing again import on those (after a cleanup -> sys.modules.clear() ) – Pablo Stark Jul 21 '14 at 12:58
  • 2
    @vaultah: I don't understand what you're trying to say. That starred imports are bad idea so that is why Python doesn't give you a way to reload those starred imports, even though Python allows the starred import in the first place. Is there a compelling reason for this asymmetry? – Anas Elghafari Jul 24 '14 at 00:45

2 Answers2

1

I think there's a way to reload all python modules. The code for Python 2.7 is listed below: Instead of importing the math module with an asterisk, you can import whatever you need.

from math import *
from sys import *

Alfa = modules.keys()
modules.clear()

for elem in Alfa:
    str = 'from '+elem+' import *'
    try:     
        exec(str)     
    except: 
        pass
Pablo Stark
  • 682
  • 10
  • 34
  • 1
    Upvote because it works and it's only a few lines, but I can't say it is *the* answer to the question. Say I am testing my project in the shell, so I do "from proj import *", and now I fix something in one of the modules of proj and I want to reload. I should write a special function to do that? When I import a module by name, I only have to call reload() on that module. Python allows starred imports but does not provide to reload those starred import modules? – Anas Elghafari Jul 24 '14 at 00:21
0

This is a complicated and confusing issue. The method I give will reload the module and refresh the variables in the given context. However, this method will fall over if you have multiple modules using a starred import on the given module as they will retain their original values instead of updating. In generally, even having to reload a module is something you shouldn't be doing, with the exception of when working with a REPL. Modules aren't something that should be dynamic. You should consider other ways of providing the updates you need.

import sys

def reload_starred(module_name, context):
    if context in sys.modules:
        context = vars(sys.modules[context])
    module = sys.modules[module_name]

    for name in get_public_module_variables(module):
        try:
            del context[name]
        except KeyError:
            pass

    module = reload(module)

    context.update(get_public_module_variables(module))

def get_public_module_variables(module):
    if hasattr(module, "__all__"):
        return dict((k,v) for (k,v) in vars(module).items() 
                if k in module.__all__)
    else:
        return dict((k,v) for (k,v) in vars(module).items() 
                if not k.startswith("_"))

Usage:

reload_starred("my_module", __name__)
reload_starred("my_module", globals())
reload_starred("my_module", "another_module")
def function():
    from my_module import *
    ...
    reload_starred("my_module", locals())
Dunes
  • 37,291
  • 7
  • 81
  • 97