Python "import" scope
Asked Answered
S

5

14

I am dealing with some python code automatically generated for me. I want to avoid manually editing these python files & hence this question/issue:

foo.py:

def foo():
  print "foo"

boo.py:

def boo():
  foo.foo()    # <-- global name 'foo' not defined
  print "boo"

bar.py:

import foo
import boo
def bar():
  boo.boo()
  print "bar"

Execution of:

python.exe bar.py

gives an error that boo did not find foo. But bar is importing both foo & boo. Shouldn't foo be automatically available to boo?

Is there a way to do so? As said boo.py is automatically generated for me & I want to avoid adding import foo to boo.py.

Thanks.

Serilda answered 23/6, 2010 at 22:41 Comment(0)
H
19

But bar is importing both foo & boo. Shouldn't foo be automatically available to boo?

No it shouldn't: import, like any other way to bind a name, binds that name in a single, specific scope, not "in all scopes you could ever possibly want it in".

Is there a way to do so? As said boo.py is automatically generated for me & I want to avoid adding import foo to boo.py

There's one very bad hack -- I wouldn't want to live with it (I'd much rather pour my energy into getting that totally broken code generator that makes boo.py fixed -- if it has such a huge bug as missing a crucial needed import, what other horrors can it have in store?!), but, hey, it ain't my funeral...;-)

Have bar.py start...:

import foo
import boo
import __builtin__
__builtin__.foo = foo

This way you've made identifier foo a "fake, artificial built-in name" (the only kind of name that is available from every scope, unless shadowed by other intervening bindings of the name in closer scopes) referring to the module foo.

NOT recommended procedure, just a temporary workaround for the horrible, glaring bug in the code generator that builds boo.py. Get that bug fixed so you can retire this hack ASAP!

Hydrostatic answered 23/6, 2010 at 22:49 Comment(2)
OK. I will ask the guys to manually add "import foo" to all these py files. And I will fix this .py generating tool later. Thanks.Serilda
@AlexMartelli I bumped into this hack and for my purposes it is good enough. But I'm still puzzled about all the implications of putting names into the __builtin__. Beside the obvious problem with name collisions, are there some other noteworthy pitfalls?Ashurbanipal
P
7

No. If you want foo to be available in boo, you need to import it in boo. The import foo that is in bar only makes foo available in the bar module.

In general, an import statement in Python is kind of like a variable definition. You could actually think of it like that: mentally replace

import boo

with

boo = __import__('boo')

(__import__ is a builtin function of the Python interpreter that either imports a module, or looks up a reference to the existing module if it's already been imported, and returns that reference)

Whatever is automatically generating boo.py is doing it wrong. It should be adding import foo somewhere within that file. You can get around it by doing this in bar.py:

import foo
import boo
boo.foo = foo

but you really shouldn't have to be doing that. (I echo what Alex Martelli said about this kind of thing being a huge hack)

Percentage answered 23/6, 2010 at 22:44 Comment(2)
OK. Thanks. I will wait for some more time for others to chime in. If anyone has some trick. Else - I got to do what I got to do!Serilda
K. We will manually add import foo to these py files for now & fix the tool later. I at times hate this "strictness" of python but over time understand that - it usually is the "right way". Thanks.Serilda
B
4

you have to import foo in boo

boo.py

import foo

def boo():
  foo.foo()    # <-- global name 'foo' not defined
  print "boo"

bar.py

import boo

def bar():
  boo.boo()
  print "bar"
Bead answered 23/6, 2010 at 22:45 Comment(3)
Circular imports indicate a design mistake.Gomez
and there are a pain to solve problems when the code is too tight coupled... refactoring is the only solution ;) that's why i love python :)Shadchan
@drevicko, Thanks, I must have misread this thread 6 years ago. Either that, or just my off-topic musing, which is also believable... ;)Gomez
P
4

Each module has its own namespace. So for boo.py to see something from an external module, boo.py must import it itself.

It is possible to write a language where namespaces are stacked the way you expect them to: this is called dynamic scoping. Some languages like the original lisp, early versions of perl, postscript, etc. do use (or support) dynamic scoping.

Most languages use lexical scoping instead. It turns out this is a much nicer way for languages to work: this way a module can reason about how it will work based on its own code without having to worry about how it was called.

See this article for additional details: http://en.wikipedia.org/wiki/Scope_%28programming%29

Portage answered 23/6, 2010 at 22:45 Comment(0)
A
-1

you can use importlib module once a module is imported it can't be reimported, Try using import module_name import importlib

importlib.reload(module_name)

But you need to import that module(module_name) first,and importlib also.

Active answered 25/12, 2020 at 9:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.