Python Child cannot use a Module the Parent Imported

22,058

Solution 1

the sqlite3 module is imported into the Parent module hence you need to access it through that module

self.db = Parent.sqlite3.connect("test.db")

It is not directly imported into the Child module unless you tell python to do so, for example

from Parent import *

Will give you access to all the members of the Parent module from within the Child module

Solution 2

The child has its own namespace and you haven't imported sqlite3 into it. So you need to import sqlite3 into Child.py. You could also do import Parent.sqlite3 and then call Parent.sqlite3.connect. There's no real advantage to doing it that way instead of just importing sqlite3, since modules are only actually imported once (at the first import the code reaches) and the following imports just add the module to the current namespace.

Solution 3

You haven't imported the sqlite3 module into the Parent class (you could, but that would be really weird). You've imported sqlite3 into the Parent.py module, which includes the Parent class, and uses the sqlite3 module in its definition.

Then a separate module imports the Parent.py module, and defines a subclass of Parent. This doesn't automatically bring everything in the Parent class into scope[1], and it certainly doesn't bring everything that was in scope when you were defining the Parent class in Parent.py into scope. If you declared other classes in Parent.py, you wouldn't expect those names to be in scope in Child just because they were in the same module as its parent class, so why would you expect this of a module that just happens to be used in defining some of Parent's methods?

You already have a reference to the namespace where sqlite3 was imported; you got the Parent class out of it in order to subclass it when you said class Child(Parent.Parent). So you could use Parent.sqlite3 to access sqlite3, but that's a very odd way to use modules in Python.

Normally it's better to just add import sqlite3 to the top of Child.py. Then anyone reading the code will see that it uses sqlite3. If the see you using sqlite3 that you've imported from Parent.py, they'll wonder why you didn't use the normal way, and think you might be doing something tricky like wrapping the sqlite3 module with some extra code you've added. And if you've just done import * from Parent, then it's not even obvious where the sqlite3 name came from, and your readers will really be confused. And your code will mysteriously stop working when you decide you don't need to import sqlite3 in Parent.py after all, but the error message won't tell you anything about Parent.py.

Generally if you're doing simple obvious things like importing a standard module, you should do it the simple and obvious way. People are used to reading that, and will take it in really easily without needing to stop and think about it. The "confused reader" that is most likely to be a problem is yourself in a a few months when you've forgotten exactly how this code worked; you want to make it as easy as possible for yourself when you get the job of figuring it out again.


[1] Inheriting from a parent class has nothing at all to do with scope, i.e. what names you can access without qualifying them. You don't get access to the parent class' methods and class variables inside the class block defining the child class. What it means is that after the child class is created, the name resolution protocol for instance and class variables will look in the Parent if they don't find things in the child class. This is a somewhat subtle point, that basically boils down to (1) within the child class block (including the definitions of methods) some_parent_method() will give you an error, but (2) after the child class exists (including when methods are actually run) Child.some_parent_method() (or self.some_parent_method() within a method) will find the parent's method.

Share:
22,058
sazr
Author by

sazr

Updated on January 22, 2020

Comments

  • sazr
    sazr over 4 years

    I have a funny import error when using Inheritence in Python.

    In a parent class I import the module sqlite3, in a child class I then try to use a sqlite3 function but I get an error saying "NameError: global name 'sqlite3' is not defined". Why does this happen & how do I fix it?

    The 2 classes are in separate files:

    Parent.py

    import sqlite3
    
    class Parent:
        def __init__(self):
    
            self.create_database()
    
        def create_database(self):
            """ Virtual function to be overriden in child classes """
            pass
    
        ...more class functions that use sqlite3 functions
    

    Child.py

    import Parent
    
    class Child( Parent.Parent ):
        def create_database(self):
            self.db = sqlite3.connect("test.db") # Error occurs HERE
    
    c = Child()
    
  • jsbueno
    jsbueno over 12 years
    Or simply use an import sqlite3 on the child module as well.
  • yantrab
    yantrab over 12 years
    Why on earth would you access sqlite3 through Parent? Also, "import *" is not great.
  • Gareth Latty
    Gareth Latty over 12 years
    Agreed, this is a bad answer to accept - import sqlite3 is the correct way to do this.
  • jdi
    jdi over 12 years
    Yes this is a poor answer. You should not be relying on sqlite3 to be supplied from the parent module import.
  • bluppfisk
    bluppfisk over 6 years
    why not? If it extends the parent, won't it be using the same module anyway? Or could another child from the same parent alter something in the behaviour of the imported module, which would then affect the other children? Like a crazy genetic engineering experiment?