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()
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With