Python logging module imported in different scripts -
in python logging tutorial, there example 2 python scripts : myapp.py
, , mylib.py
the code :
# myapp.py import logging import mylib def main(): logging.basicconfig(filename='myapp.log', level=logging.info) logging.info('started') mylib.do_something() logging.info('finished') if __name__ == '__main__': main()
and
# mylib.py import logging def do_something(): logging.info('doing something')
what don't how fact using basicconfig
in myapp.py
changes logging behavior in mylib.py
.
i thought in python, when import same module in 2 different scripts, disconnected because first 1 becomes myapp.logging
, second 1 mylib.logging
.
edit :
i changed mylib.py code
# mylib.py import logging def do_something(): logging.warning('doing something') do_something()
when run myapp.py, logs printed in console , not appear in log file anymore. how possible?
there's bug (if can call that) in understanding of python's modules:
i thought in python, when import same module in 2 different scripts, disconnected because first 1 becomes
myapp.logging
, second 1mylib.logging
.
this not case.
the import
statement interpreted when encountered, , when run python on main program (python myapp.py
or equivalent), executes these lines:
import logging
(which imports logging
module),
import mylib
(which imports library mylib.py
),
def main():
(which binds name main
compiled bytecode of function), and:
if __name__ == '__main__': main()
(which runs main
since local name __name__
in fact bound string compares equal string __main__
).
so far, not surprising (except perhaps def main()
run @ point it's encountered in import of myapp.py
).
the part is surprising happens during execution of 2 import
statements.
the import machinery has evolved bit (and different in python3 python2) in essence these various things:
- locate file (using
sys.path
) - if first import of file, run executable statements in file
- use or modify
sys.modules
(see below) - bind resulting object(s) (something of
<type 'module'>
, or name within that) name(s) supply (implicitly regularimport
, explicitlyfrom ... import ... name
).
one of key items here italicized part above. module run on first import
. result of successful import module instance, added sys.modules
dictionary:
$ python2 ... >>> import sys >>> x = sys.modules['copy_reg'] >>> print x <module 'copy_reg' '/usr/local/lib/python2.7/copy_reg.pyc'>
if, @ point, ask python re-import module, quietly nothing:
>>> import copy_reg >>>
what happens here python notices module loaded , in sys.modules
extracts already-loaded module entity (the 1 bound symbol x
above). binds name copy_reg
already-existing module. if import copy_reg y
:
>>> import copy_reg y
the name additionally bound symbol y
:
>>> print x, y, copy_reg <module 'copy_reg' '/usr/local/lib/python2.7/copy_reg.pyc'> <module 'copy_reg' '/usr/local/lib/python2.7/copy_reg.pyc'> <module 'copy_reg' '/usr/local/lib/python2.7/copy_reg.pyc'>
to see these in fact same module, can use id
function, prints internal address of underlying object:
>>> print id(x), id(y), id(copy_reg) 34367067648 34367067648 34367067648
(a different run of python, or different version, might produce different set-of-3 address values here, 3 match, because these refer same module).
in case, in main
in myapp
, symbol logging
refers same logging
module symbol logging
in mylib
.
in original code, call (from do_something
in mylib
) logging.warning
print message after main
in myapp
has called logging configuration code. log message therefore goes directed.
in edit, you've changed mylib
unconditionally call (via do_something
) logging.warning
function import mylib
statement loads myilb
create module. happens on in myapp
, before binding main
code , before calling main
. that message comes out on console.
it's logging code decide whether obey (later) basicconfig
call, made main
. can see own example, not honor attempt redirect root configuration after printing message (this because it's set internal log handlers then, recall).
Comments
Post a Comment