Re-import module?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
pythoncoder
Posts: 1564
Joined: Fri Jul 18, 2014 8:01 am

Re: Re-import module?

Postby pythoncoder » Thu Nov 27, 2014 5:50 am

TFT, as usual this pensioner is behind the curve ;) At least we now have a specific piece of Cpython functionality to discuss.
Peter Hinch

User avatar
polygontwist
Posts: 36
Joined: Sat Jun 28, 2014 4:54 pm
Location: Germany, Rostock
Contact:

reimport imported Modules (del ?)

Postby polygontwist » Sun Nov 30, 2014 7:28 pm

Hello,
How can I delete an imported module to import it again?
I found the command "del",it works(?) but it does not delete the imported module.

I write .py files and would like to import again without resetting the board.
(edit: v1.3.4-1-g3e42570 on 2014-10-22)

pfalcon
Posts: 932
Joined: Fri Feb 28, 2014 2:05 pm

Re: Re-import module?

Postby pfalcon » Sat Dec 05, 2015 12:25 pm

sys.modules is now implemented, so it's possible to trigger re-importing of a module.

SpotlightKid
Posts: 190
Joined: Wed Apr 08, 2015 5:19 am

Re: Re-import module?

Postby SpotlightKid » Fri Dec 11, 2015 11:38 am

Very good!

User avatar
pythoncoder
Posts: 1564
Joined: Fri Jul 18, 2014 8:01 am

Re: Re-import module?

Postby pythoncoder » Sun Dec 13, 2015 10:37 am

@pfalcon Very useful!
@polygontwist In case you didn't follow @pfalcon's post, Python caches imported modules in a dictionary called sys.modules. This caters for the case where a module gets imported more than once: if it's in the dictionary Python doesn't bother re-importing it. So, if you want to re-import module foo, with a new firmware build issue

Code: Select all

import sys
del sys.modules['foo']
import foo
Peter Hinch

User avatar
Roberthh
Posts: 644
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Re-import module?

Postby Roberthh » Sun Dec 13, 2015 8:14 pm

Basically that works and is very useful. But if the first loaded module contains and registers an ISR, this one will be called, and any signaling using a global symbol will not work, since the first loaded ISR and the secondly loaded module will stare at different places At least that's what I observed when I tried to use the approach after pfalcon announced it. And obviously, the first loaded modules still sits in memory.

SpotlightKid
Posts: 190
Joined: Wed Apr 08, 2015 5:19 am

Re: Re-import module?

Postby SpotlightKid » Sun Dec 13, 2015 8:33 pm

Roberthh wrote:But if the first loaded module contains and registers an ISR, this one will be called, and any signaling using a global symbol will not work,


Thats one reason why using module globals to keep state is usually bad programming practice and executing code on import (e.g. registering an ISR) even more so. The same problems would exist with CPython. It also can't magically update any existing object instances from the re-imported module to use the new code.

User avatar
dhylands
Posts: 2374
Joined: Mon Jan 06, 2014 6:08 pm
Location: Shuswap, BC, Canada
Contact:

Re: Re-import module?

Postby dhylands » Sun Dec 13, 2015 9:02 pm

SpotlightKid wrote:
Roberthh wrote:But if the first loaded module contains and registers an ISR, this one will be called, and any signaling using a global symbol will not work,


Thats one reason why using module globals to keep state is usually bad programming practice and executing code on import (e.g. registering an ISR) even more so. The same problems would exist with CPython. It also can't magically update any existing object instances from the re-imported module to use the new code.


So wouldn't loading the module the second time - reregister the ISR, thus replacing the old definition?

There is still a window where if the ISR occurs between deleting the old module and re-importing the new one where it will still point to the old routine, but as soon as the new ISR is registered, the old one should go away. There are some exceptions (like Exti) where if you were planning on using reimporting, then I would register an ISR of None, first, and then register the new ISR.

User avatar
Roberthh
Posts: 644
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Re-import module?

Postby Roberthh » Mon Dec 14, 2015 5:57 am

Actually in the example code I used the ISR was registered by a function in the loaded module, not at load time of the module, and the interrupt is caused by a one-shot timer. I may set up an example where the interrupt is triggered by an external pulse generator, where I can better control how many events occur. And thinking about SpotLightKid's comments, it could also be that it is the global which is not updated. I could try to look further. In any case, I would expect that loading a module would replace or re-use previous symbol definitions.
And, b.t.w., there was not specific reason to use that example code. It was just a short piece of code at hand that was loaded to the WiPy.
----- Update ----
Trying to simplify the test, it looks as if runs everything as expected on PyBoard. Here is the short test code:

Code: Select all

import sys
from pyb import Timer, LED
fired = None

def reload(time=1):
    global fired
    print ("Enter the magic ANYKEY or 'q' to quit")
    tim = Timer(1)
    tim.init(freq = time)
    tim.callback(my_interrupt)

    while True:
        fired = False
        ch = sys.stdin.read(1)
        print ("{!r} {} ".format(ch, fired), end="")
        if ch == "q":
            tim.deinit()
            print ("")
            break

def my_interrupt(timer):
    global fired
    fired = True
    LED(1).toggle()

I can delete the module from sys.modules, change the code (e.g. by choosing LED(2)), reimport it, and then the other led lights up, and the stae of 'fired' is changed too. A similar code on WiPy w/o LED behaves strange. I can load it once, it triggers the 'fired' flag. But if I quit and call the function again, the flag is never changed again, until I do a HARD reset. Thats with build 1.5.1-116. That seems to be the reason why I assumed that reloading did not work. Here's the Wipy code:

Code: Select all

import sys
from machine import Timer
fired = None

def reload(time = 1000000):
    global fired
    tim = Timer(1)
    tim.init(mode = Timer.ONE_SHOT, width = 32)
    print ("Enter the magic ANYKEY or 'q' to quit")

    while True:
        tim_ch = tim.channel(Timer.A | Timer.B, period = time)
        tim_ch.irq(handler = my_interrupt)
        fired = False
        ch = sys.stdin.read(1)
        print ("{!r} {} ".format(ch, fired), end="")
        if ch == "q":
            tim.deinit()
            print ("")
            break

def my_interrupt(timer):
    global fired
    fired = True

User avatar
pythoncoder
Posts: 1564
Joined: Fri Jul 18, 2014 8:01 am

Re: Re-import module?

Postby pythoncoder » Thu Dec 17, 2015 10:02 am

For all its limitations reload can be very useful. I've put the following in boot.py (so that reload appears in Python's namespace).

Code: Select all

def reload(mod):
    import sys
    z = __import__(mod)
    del z
    del sys.modules[mod]
    return __import__(mod)
It differs from the Python standard function in that the name of the module to be reloaded must be passed as a string:

Code: Select all

PYB: sync filesystems
PYB: soft reboot
MicroPython v1.5.1-127-g67a5bfc on 2015-12-17; PYBv1.1 with STM32F405RG
Type "help()" for more information.
>>> import cow
0
>>> reload('cow')
0
<module 'cow' from 'cow.py'>
>>>
Perhaps someone fancying a puzzle for the festive season can fix this?
Peter Hinch


Return to “General Discussion and Questions”

Who is online

Users browsing this forum: No registered users and 2 guests