Import, Inheritance, Scoping -- I'm doing something wrong with one of these

Peter Otten __peter__ at web.de
Sat Mar 7 12:23:49 EST 2009


Elijah Newren wrote:

> Hi,
> 
> I have three files in a simple testcase, and when I run
>   $ main.py callee.options
> This comes back with a Traceback pointing out the following error:
>   File "callee.options", line 5, in __init__
>     Foo.__init__(self, value)
> NameError: global name 'Foo' is not defined
> 
> 
> The three files are:
> 
> ---------------  main.py  ---------------
> #!/usr/bin/env python
> 
> import sys
> 
> class Stuff:
>   def __init__(self, filename):
>     self.greeting = 'Hi world'
>     self.filename = filename
> 
>   def run(self):
>     print self.greeting
>     execfile(self.filename)
> 
> work = Stuff(sys.argv[1])
> work.run()
> ---------------  somelib.py  ---------------
> class Foo:
>   def __init__(self, value):
>     self.value = value
> 
>   def do_stuff(self):
>     raise NotImplementedError()
> 
> class OfficialBar(Foo):
>   def __init__(self, value):
>     Foo.__init__(self, value)
> 
>   def do_stuff(self):
>     print self.value
> ---------------  callee.options  ---------------
> from somelib import Foo, OfficialBar
> 
> class MyBar(Foo):
>   def __init__(self, value):
>     Foo.__init__(self, value)
>     #super(MyBar, self).__init__(value)
> 
>   def do_stuff(self):
>     print 2 * self.value + 1
> 
> 
> baz = MyBar(7)
> #baz = OfficialBar(7)
> baz.do_stuff()
> ---------------------------------------------
> 
> If I comment out the baz = MyBar(7) line, and uncomment the baz =
> OfficialBar(7) line, then there's no error.
> 
> I'm sure this is somehow related to the fact that the execfile is
> within the Stuff class scope, and thus my import statements are
> working under some nested scope, but I don't know how to fix it (other
> modifying main.py to remove the Stuff class entirely, but in my real
> testcase I only have access to the callee.options file).  I'm sure
> this is covered in some FAQ or post somewhere, but I seem to be coming
> up short in my search.  If someone could someone point me to the
> relevant FAQ or post, I'd be more than happy to go read it.

execfile puts Foo in the local namespace of the Stuff.run() method, then
MyBar.__init__() looks it up in the global namespace and fails.

A quick and dirty fix may be to modify execefile to

    execfile(self.filename, globals())

but you should seriously consider renaming callee.options and importing it
the normal way.

Peter



More information about the Python-list mailing list