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

Peter Otten __peter__ at web.de
Sat Mar 7 21:54:03 CET 2009


Elijah Newren wrote:

> Hi,
> 
> For some reason, Peter Otten's response is not showing up in my inbox,
> but did show up in the mailing list archives
> (http://mail.python.org/pipermail/python-list/2009-March/703850.html).
>  So I'll respond to my own email, quote him, and respond that way.
> 
> On Sat, Mar 7, 2009 at 9:46 AM, Elijah Newren <newren at gmail.com> 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()
>> ---------------------------------------------
> 
> 
> 
> And Peter Otten wrote:
>> 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.
> 
> Ah, thanks for the explanation.  The big problem here is that real
> case from which I drew main.py and somelib.py is cvs2svn.  I'm using a
> system installed version of cvs2svn, and thus I only have control of
> callee.options.  

Yea, I didn't read carefully enough.

> However, using your hint, I solved my problem by 
> changing the first line of callee.options from
> 
> from somelib import Foo, OfficialBar
> 
> to
> 
> global Foo
> _temp = __import__('somelib', globals(), locals(), ['Foo', 'OfficialBar'])
> Foo = _temp.Foo
> OfficialBar = _temp.OfficialBar
> 
> 
> Yeah, I agree it's ugly, but it's a use-once program anyway.  :-)
> 
> Thanks again,
> Elijah

I think moving options.callee's body into a function would also work:

#untested
def callee():
    from somelib import Foo, OfficialBar

    class MyBar(Foo):
          def __init__(self, value):
              Foo.__init__(self, value)
 
          def do_stuff(self):
              print 2 * self.value + 1


    baz = MyBar(7)
    baz.do_stuff()

callee()




More information about the Python-list mailing list