User class import error after no changes to previously perfectly working code.



  • Hello All,

    I have come across a strange and very frustrating error when I tried to upload my code at the start of this week, having just completed and thoroughly tested it over the weekend.

    I have an LCD module that is dependent on a SPI I/O expander to give it commands that are sent from my SiPy board. I have two python code files that contain a good 100 lines of code each, that contain commands for the LCD module and the I/O expander respectively.

    I have been using the Visual Studio Code Pymakr Plugin as I couldn't get the Atom Plugin to upload my code. I am presuming there was a plugin update and that was why VSC was giving me strange errors all of a sudden but I updated both the SiPy firmware and Visual Studio and even re-installed the plugin with no improvements.

    To give some details, I am trying to import two user-defined classes from two different external files into my main.py file which has never thrown any errors before, usually I would think that this is a personal error but the code was working perfectly on Saturday and nothing has been changed my end. Hence my assumption that this is a bug in whatever update that has been released.

    Import Code: (main.py)

    import MCP23S17
    from MCP23S17 import MCP23S17Backend # this imports fine?
    import LCD
    from LCD import LCDBackend # this throws an error ???

    There is no difference in the declaration of these classes, other than their location i.e. in different .py files but they are still in the same directory as main.py?!

    Log:

    Traceback (most recent call last):
    File "main.py", line 4, in <module>
    ImportError: no module named 'LCD.LCDBackend'
    MicroPython v1.8.6-796-g489fafa0 on 2017-10-15; SiPy with ESP32
    Type "help()" for more information.

    Even more confusingly it seems pretty arbitrary what user-defined classes it rejects all of a sudden. I'm not finding a solution to this problem and after having spent weeks debugging only to have it fail so soon after I had it working has left me with little patience. It doesn't help having a deadline as well and I have even tried compiling it on another computer. This fault is not isolated to one project either I have another sub-system that I am developing that is around 500 lines of code with exactly the same problem!

    Can someone please shine some light on this please? Thank you in advance.



  • @livius

    Yes, I had a similar thought, it makes sense with the RTC as there are similarly named Pycom API modules I imagine it might clash with, but that still doesn't explain why it failed suddenly overnight. It might be a mixture of things. There is no LCD module in the Pycom documentation as far as I am aware so this is still a mystery as well. I will have to be more obscure with my naming systems ;)



  • @josh
    it is not good to have common name like RTC.py
    this is simillar problem as computer name like COM1 ;-)



  • @robert-hh

    Hi guys, thanks for all your suggestions and Robert, thanks for testing my code, that's strange that it worked, I used two different computers and even I got the same issue using the atom plugin!

    I have however, fixed the problem!

    The glitch is still there, I have just found a way to avoid it.

    I was playing around with farfetched solutions late last night, one of which included changing the file name... which worked!?! My theory being that it was having problems seeing anything above main.py in the file-system so I changed the name to zLCD.py which put it at the bottom, like I said, farfetched...

    This still doesn't seem to be the root problem however, as I then changed the name to aLCD.py which put it at the top, but this also worked. It seemed it just has problems with certain file names all of a sudden. This problem really came at an inconvenient time as I have lost days on my project now!

    I have another project with a similar problem file with the name RTC.py, but it seems pretty arbitrary what file names it doesn't like. e.g. it compiles my MCP23S17.py file perfectly.

    Xykon, I tried putting my modules in a lib sub-folder in my project hierarchy to sync to the internal file-system but this also had no effect on the problem, although perhaps I was doing this wrong.

    I seem to be the only one with this problem it would be nice to know if it is isolated to me or not.



  • @livius After a little bit of thinking the problem could be, that LCD is already defined in MCP23S17.py, which causes the 'import LCD' statement to be ignored, and the following one raises an error.



  • @josh
    Will be better - if code is not confidential -
    tu put LCD.py code then we can see where the problem is.



  • @josh OK. So I gave it a try on my WiPy. The lcd.py file looks like:

    #
    class LCDBackend:
        def __init__(self, LCD_SPI_Object, LCD_SPI_CS):
            print("In LCDBackend")
    

    And the main.py looks either like:

    import lcd # this can be removed with no change
    
    import machine # no errors
    from machine import SPI # no errors
    from machine import Pin # no errors
    
    _SPI_Ref = SPI(0, mode=SPI.MASTER, baudrate=10000, polarity=0, phase=0, firstbit=SPI.MSB)
    _LCD_CS_Ref = Pin('P9', mode=Pin.OUT)
    
    X = lcd.LCDBackend(_SPI_Ref, _LCD_CS_Ref) # class instance "X"
    

    or

    from lcd import LCDBackend # this throws a "no module named ..." error
    
    import machine # no errors
    from machine import SPI # no errors
    from machine import Pin # no errors
    
    _SPI_Ref = SPI(0, mode=SPI.MASTER, baudrate=10000, polarity=0, phase=0, firstbit=SPI.MSB)
    _LCD_CS_Ref = Pin('P9', mode=Pin.OUT)
    
    X = LCDBackend(_SPI_Ref, _LCD_CS_Ref) # class instance "X"
    

    or

    import lcd # this can be removed with no change
    from lcd import LCDBackend # this throws a "no module named ..." error
    
    import machine # no errors
    from machine import SPI # no errors
    from machine import Pin # no errors
    
    _SPI_Ref = SPI(0, mode=SPI.MASTER, baudrate=10000, polarity=0, phase=0, firstbit=SPI.MSB)
    _LCD_CS_Ref = Pin('P9', mode=Pin.OUT)
    
    X = LCDBackend(_SPI_Ref, _LCD_CS_Ref) # class instance "X"
    

    No problems. I omitted the other imports, because I do not have that file. I used small letters for file names, but did not check whether that is the reason.


  • administrators

    Hello Josh,

    First off I would suggest to put all your library code into the lib subfolder on the module.

    It might be worth trying to upload your code via ftp (see https://docs.pycom.io/chapter/toolsandfeatures/FTP.html) in case there is an upload issue with the Pymakr plugin.

    If this still doesn't help please feel free to email me directly (cehlers@pycom.io) and attach your code for testing (I will assure your code will be kept strictly confidential).



  • @robert-hh Thank you very much!



  • @josh I have not LoPy/WiPy here at the moment. I'll check this night.



  • @robert-hh

    Hi Robert,

    That's useful to know, thanks!



  • @josh: Just a hint: Code sections in the post can be enclosed with lines each containing three backticks(```). Then the formatting is kept.



  • @josh

    For some additional information:

    main.py:

    import MCP23S17
    from MCP23S17 import MCP23S17Backend # this doesn't throw errors?
    import LCD # this can be removed with no change
    from LCD import LCDBackend # this throws a "no module named ..." error

    import machine # no errors
    from machine import SPI # no errors
    from machine import Pin # no errors

    _SPI_Ref = SPI(0, mode=SPI.MASTER, baudrate=10000, polarity=0, phase=0, firstbit=SPI.MSB)
    _LCD_CS_Ref = Pin('P9', mode=Pin.OUT)

    X = LCDBackend(_SPI_Ref, _LCD_CS_Ref) # class instance "X"
    This throws errors when I either use:
    from "LCD import *" or
    "LCD.LCDBackend()" with "import LCD" only
    i.e. when i don't use "from LCD import LCDBackend"

    LCD.py:

    class LCDBackend:
    [indent] def init(self, LCD_SPI_Object, LCD_SPI_CS):
    the forum formatting has removed the double underscores from init
    [double indent] ... rest of the code

    Hopefully this helps.



  • @robert-hh

    Hi Robert,

    I have tried what you suggested by using " import LCD " and then calling the member with " LCD.LCDBackend() " with yet more import errors.

    The fact is the underlying problem still remains: all my code was previously working perfectly and having made no changes to it originally it started giving me these errors for no reason. I have 3 previously working projects that have the exact same problem, all unchanged, that all fail now for no reason. I have even tried moving the project directory around my computer file system.

    I cannot fathom what is wrong, other than a bug of some sort...



  • @josh if you need both the class and the member, use
    import LCD
    and call the member e.g. like
    LCD.LCDBackend
    In the module.member way.
    But it hard to tell what you want w/o a view on the code you are struggling with.



  • @robert-hh

    Hi Robert,

    Thanks again for your reply.

    I have tried what you stated, both " from LCD import * " (this is a useful syntax) and " from LCD import LCBBackend " both with and without the redundant " import LCD ". Both of these methods still throw errors.

    The " from LCD import * " gets me past the import error but then can't then find the class in the module.

    Log:

    Traceback (most recent call last):
    File "main.py", line 9, in <module>
    NameError: name 'LCDBackend' is not defined
    MicroPython v1.8.6-796-g489fafa0 on 2017-10-15; SiPy with ESP32
    Type "help()" for more information.

    As an additional experiment I removed the LCD.py entirely from the project hierarchy and it only then throws an error when I try to instantiate the class. With the import code " from LCD import * "

    When I use the import code " from LCD import LCDBackend " it throws the error at this line.

    Almost as if it only goes looking for it, when you explicitly reference it!

    " import LCD " it seems, does nothing and it doesn't even matter if LCD.py isn't in the hierarchy until you explicitly reference it. Which raises the question as to if it can even perceive it in the hierarchy to begin with. Which makes me think that the plugin has changed, now requiring something like a specific directory for user-defined classes and namespaces? It would be great if the devs could shed some light on this.



  • @josh Yes. because then it you must include the class name: LCD.LCDBackend
    Alternatively, if you need more than just LCDBackend, you could write:
    from LCD import *
    If you just need LCDBackend, write only:
    'from LCD import LCBBackend



  • @robert-hh

    Hi Robert,

    Thanks for your quick reply.

    Yes I am still getting my head around Python having being used to working in C++ and Java, it does seem like some of those lines are redundant but they have worked before now despite that.

    I have tried your suggestion of taking them out and just importing the entire module but when I go to initialise the class later in the code i.e. LCDBackend() it says it isn't defined.

    Log:

    Traceback (most recent call last):
    File "main.py", line 13, in <module>
    NameError: name 'LCDBackend' is not defined
    MicroPython v1.8.6-796-g489fafa0 on 2017-10-15; SiPy with ESP32
    Type "help()" for more information.

    Still puzzling...



  • This post is deleted!


  • @josh said in User class import error after no changes to previously perfectly working code.:

    import LCD
    from LCD import LCDBackend # this throws an error ???

    These two lines looks strange to me, since in the first you import the while module, and in the second only one element.
    After the first import, a symbol called LCD.LCDBackend already exists. If you need only MCP23S17 and LCDBackend, the lines import MCP23S17 and import LCDBackend are not required.
    So I'm more surprised not already line 2 throws an error.


Log in to reply
 

Pycom on Twitter

Looks like your connection to Pycom Forum was lost, please wait while we try to reconnect.