testimport
├── __init__.py
├── logging.py
└── util.py
__init__.py
包含:
from __future__ import ( absolute_import, division, print_function, unicode_literals )
import logging # imports standard library module (because absolute_import is activated)
_logging_file = logging.__file__
from .util import testlog
if _logging_file != logging.__file__:
# at this point, `logging` no longer points to the standard
# library module, but the local logging module instead(!)
raise AssertionError('`logging` overwritten; {!r} is not equal to {!r}'.format(_logging_file, logging.__file__))
LOGGER = logging.getLogger(__name__)
logging.py
包含:
import sys
__all__ = ()
SILENT = -(sys.maxsize) - 1
util.py
包含:
from __future__ import ( absolute_import, division, print_function, unicode_literals )
import logging # imports standard library module (because absolute_import is activated)
from .logging import SILENT # this is (perversely) where the importing module's `logging` gets overridden
__all__ = ( 'testlog' )
_LOGGER = logging.getLogger(__name__)
def testlog(log_lvl=SILENT):
_LOGGER.log(log_lvl, 'Hello!')
AssertionError
import
时会引发testimport
:
% python
Python 2.7.10 (default, Sep 24 2015, 10:13:45)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testimport
<function testlog at 0x10e86e1b8>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "testimport/__init__.py", line ..., in <module>
raise AssertionError('`logging` overwritten; {!r} is not equal to {!r}'.format(_logging_file, logging.__file__))
AssertionError: `logging` overwritten; '/.../lib/python2.7/logging/__init__.pyc' is not equal to 'testimport/logging.pyc'
为什么发生这种情况?
更新,当使用pdb
单步执行此操作时,from .logging import SILENT
中的违规指令似乎为util.py
,但我不明白为什么。这是repo版本的缩写会话:
% echo 'import testimport' >|testme.py
% python -m pdb testme.py
(Pdb) s
--Call--
> /.../testimport/testimport/__init__.py(1)<module>()
-> from __future__ import (
(Pdb) b 12
Breakpoint 1 at /.../testimport/testimport/__init__.py:12
(Pdb) c
> /.../testimport/testimport/__init__.py(12)<module>()
-> from testimport.util import testlog
(Pdb) s
--Call--
> /.../testimport/testimport/util.py(1)<module>()
-> from __future__ import (
(Pdb) b 5
Breakpoint 2 at /.../testimport/testimport/util.py:5
(Pdb) c
> /.../testimport/testimport/util.py(5)<module>()
-> from .logging import SILENT
(Pdb) u
> /.../testimport/testimport/__init__.py(12)<module>()
-> from testimport.util import testlog
(Pdb) p logging
<module 'logging' from '/.../lib/python2.7/logging/__init__.pyc'>
(Pdb) d
> /.../testimport/testimport/util.py(5)<module>()
-> from .logging import SILENT
(Pdb) s
--Call--
> /.../testimport/testimport/logging.py(1)<module>()
-> from __future__ import (
(Pdb) b 6
Breakpoint 3 at /.../testimport/testimport/logging.py:6
(Pdb) c
> /.../testimport/testimport/logging.py(6)<module>()
-> SILENT = -(sys.maxsize) - 1
(Pdb) u
> /.../testimport/testimport/util.py(5)<module>()
-> from .logging import SILENT
(Pdb) u
> /.../testimport/testimport/__init__.py(12)<module>()
-> from testimport.util import testlog
(Pdb) p logging
<module 'logging' from '/.../lib/python2.7/logging/__init__.pyc'>
(Pdb) s
> /.../testimport/testimport/util.py(7)<module>()
-> 'testlog',
(Pdb) u
> /.../testimport/testimport/__init__.py(12)<module>()
-> from testimport.util import testlog
(Pdb) p logging
<module 'testimport.logging' from 'testimport/logging.pyc'>
答案 0 :(得分:0)
子模
当使用任何机制(例如
importlib
API,import
或import-from
语句或内置__import__()
)加载子模块时,会在父模块对子模块对象的命名空间。...
鉴于Python熟悉的名称绑定规则,这似乎令人惊讶,但它实际上是导入系统的基本功能。
在Python 3.4之前似乎没有这种解释,但会影响所有版本的Python。请参阅Python issue #24029。
在上面的示例中,testimport.logging
必然是指本地模块。导入它(从任何地方)将其安装在testimport
中(如预期的那样)。毫无疑问,这必然会取代logging
的任何现有testimport
成员。