Python import as global name not defined -
i have application runs on postgres & mysql. each program checks determine database , imports either postgres_db db_util or mysql_dt db_util. works when code in main references db_util, if class imported, reference db_util not defined.
i created following classes , main test problem , found interesting side effect. classes b & c reference classa under different import cases. b & c identical except b in main , c imported.
classx.py
class classa(object): def print_a(self): print "this class a" class classc(object): def ref_a(self): print 'from c ref ==>', xa=classa() xa.print_a() def ref_ca(self): print 'from c ref ca ==>', xa=ca() xa.print_a()
test_scope.py
from classes.classx import classa classes.classx import classa ca classes.classx import classc cb class classb(object): def ref_a(self): print 'from b ref ==>', xa=classa() xa.print_a() def ref_ca(self): print 'from b ref ca ==>', xa=ca() xa.print_a() print 'globals:',dir() print 'modules','ca:',ca,'cb:',cb,'ca:',classa print '' print 'from main' xb=classb() xb.ref_a() xb.ref_ca() print '' print 'from imports' xbs=cb() xbs.ref_a() xbs.ref_ca()
and results:
globals: ['classa', 'classb', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'ca', 'cb'] modules ca: <class 'classes.classx.classa'> cb: <class 'classes.classx.classc'> ca: <class 'classes.classx.classa'> main b ref ==> class b ref ca ==> class imports c ref ==> class c ref ca ==> traceback (most recent call last): file "test_scope.py", line 32, in <module> xbs.ref_ca() file "r:\python\test_scripts\scope\classes\classx.py", line 13, in ref_ca xa=ca() nameerror: global name 'ca' not defined press key continue . . .
from test, see object ca (imported as) not available classc, however, module classa available (imported without as).
- why difference between import , import behavior? unclear why mains globals not available classes main imports.
- what approach dynamically determine appropriate db_util module import , have accessible other imported classes?
update: after reading yet post on namespaces: "visibility of global variables imported modules", understand in example above reason classa available classc & c in same imported file, same namespace.
so remaining question design question:
if have code this:
if db == 'mysql': mysql_db import db_util elif db == 'postgres' postgres_db import db_util
what approach make db_util available imported modules?
update:
from reponse blckknght, added code
cb.ca =ca
to scope_test script. requires class call xa=ca() changed xa=self.ca(). think adding objects class outside class, though python allows it, not design methodology , make debugging nightmare.
however, since think modules , classes should standalone or declare dependencies, going implement class this, using code sample above.
break out classa , classc separate modules , @ top of classc, before class definition, imports
from classa import classa classa import classa ca class classb(object):
and in real situation, need import db_util module several modules
ci.py #new module select class appropriate db
if db == 'mysql': mysql_db import db_util elif db == 'postgres' postgres_db import db_util
in each module needing db_util class
import ci db_util=ci.db_util #add db_util module globals class module(object):
one problem requires each module using db_util import it, make dependencies known.
i close question , want thank blckknght , armin rigo responses clarify issue me. appreciate design related feedback.
in python, each module has it's own global namespace. when import, you're adding imported modules current module's namespace, not namespace of other module. if want put in namespace, need tell python explicitly.
main.py:
if db == "mysql": # or whatever real logic import mysql_db db_util elif db == "postgres": import postgres_db db_util import some_helper_module some_helper_module.db_util = db_util # explicitly add namespace #...
other modules:
import some_helper_module db = some_helper_module.db_util.connect() # or whatever real api #...
note can't use main module (which executed script) shared namespace. that's because python uses module's __name__
attribute determine how cache module (so same object multiple imports), script given __name__
of "__main__"
rather real name. if module imports main
, they'll separate (duplicate) copy!
Comments
Post a Comment