Import, Inheritance, Scoping -- I'm doing something wrong with one of these
Peter Otten
__peter__ at web.de
Sat Mar 7 15:54:03 EST 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