Python “import” scope

2019-01-19 20:07发布

问题:

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.

回答1:

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!



回答2:

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"


回答3:

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



回答4:

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)



标签: python import