How to reload python module imported using `from module import *`

前端 未结 8 1933
挽巷
挽巷 2020-12-02 14:12

I saw in this useful Q&A that one can use reload(whatever_module) or, in Python 3, imp.reload(whatever_module).

My question is, what if

相关标签:
8条回答
  • 2020-12-02 14:39

    A cleaner answer is a mix of Catskul's good answer and Ohad Cohen's use of sys.module and direct redefinition:

    import sys
    Y = reload(sys.module["X"]).Y  # reload() returns the new module
    

    In fact, doing import X creates a new symbol (X) that might be redefined in the code that follows, which is unnecessary (whereas sys is a common module, so this should not happen).

    The interesting point here is that from X import Y does not add X to the namespace, but adds module X to the list of known modules (sys.modules), which allows the module to be reloaded (and its new contents accessed).

    More generally, if multiple imported symbols need to be updated, it is then more convenient to import them like this:

    import sys
    reload(sys.module["X"])  # No X symbol created!
    from X import Y, Z, T
    
    0 讨论(0)
  • 2020-12-02 14:44

    Never use import *; it destroys readability.

    Also, be aware that reloading modules is almost never useful. You can't predict what state your program will end up in after reloading a module, so it's a great way to get incomprehensible, unreproduceable bugs.

    0 讨论(0)
  • 2020-12-02 14:44

    A

    from module import *
    

    takes all “exported” objects from module and binds them to module-level (or whatever-your-scope-was-level) names. You can reload the module as:

    reload(sys.modules['module'])
    

    but that won't do you any good: the whatever-your-scope-was-level names still point at the old objects.

    0 讨论(0)
  • 2020-12-02 14:45

    I agree with the "don't do this generally" consensus, but...

    The correct answer is:

    import X
    reload(X)
    from X import Y  # or * for that matter
    
    0 讨论(0)
  • 2020-12-02 14:48

    When importing using from whatever_module import whatever, whatever is counted as part of the importing module, so to reload it - you should reload your module. But just reloading your module you will still get the old whatever - from the already-imported whatever_module, so you need to reload(whatever_module), and than reload your module:

    # reload(whatever_module), if you imported it
    reload(sys.modules['whatever_module'])
    reload(sys.modules[__name__])
    

    if you used from whatever_module import whatever you can also consider

    whatever=reload(sys.modules['whatever_module']).whatever
    

    or

    whatever=reload(whatever_module).whatever
    
    0 讨论(0)
  • 2020-12-02 14:53

    I've found another way to deal with reloading a module when importing like:

    from directory.module import my_func
    

    It's nice to know how do modules are being imported generally. The module is searched in sys.modules dictionary. If it already exists in sys.modules - the module will not be imported again.

    So if we would like to reload our module, we can just remove it from sys.modules and import again:

    import sys
    from directory.module import my_func
    my_func('spam')
    # output: 'spam'
    
    # here I have edited my_func in module.py
    
    my_func('spam') # same result as above
    #output: 'spam'
    
    
    del sys.modules[my_func.__module__]
    from directory.module import my_func
    
    my_func('spam') # new result
    #output: 'spam spam spam spam spam'
    

    If You would like to get reloaded module when running whole script, you could use exception handler:

    try:
        del sys.modules[my_func.__module__]
    
    except NameError as e:
        print("""Can't remove module that haven't been imported.
        Error: {}""".format(e))
    
    from utils.module import my_func
    
    ..........
    # code of the script here
    
    0 讨论(0)
提交回复
热议问题