开发者

__import__() calls __init__.py twice?

I was just wondering why __import__() calls a __init__ module twice when loading a package.

test.py
testpkg/
        __init__.py

test.py:

pkg = __import__("testpkg", fromlist=[''])

__init__.py:

print "Called."

After calling py开发者_JAVA百科thon test.py, Called. will be printed out twice. Why does python execute the __init__ "module" twice?


This is a Python bug. Passing the null string as an element of fromlist is illegal, and should raise an exception.

There's no need to include "" in fromlist; that's implicit--the module itself is always loaded. What's actually happening is the module.submodule string is using the null string, resulting in the module name testpkg., with a trailing period. That gets imported literally, and since it has a different name than testpkg, it's imported as a separate module.

Try this:

pkg = __import__("testpkg", fromlist=[''])
import sys
print sys["testpkg"]
print sys["testpkg."]

... and you'll see the duplicate module.

Someone should probably file a ticket on this if there isn't already one; too tired to do it myself right now.


Using the fromlist=[''] hack to import a specific module is explicitly frowned upon by python-dev. While it has been filed as an issue, the chances of it being fixed are low specifically because this is viewed as a mis-use of fromlist to begin with instead of necessarily a bug and a better solution is available.

What you should be doing is using importlib.import_module (available in the standard library for Python 2.7 and Python 3.1, or from PyPI with compatibility back to Python 2.3 along with being included in Django since 1.1 as django.utils.importlib). It will prevent this problem from happening, provides a better programmatic interface for importing modules, and even lets you use relative imports when you specify the package you are importing from.

If you really cannot use importlib (e.g., PyPI dependencies are not allowed even though the code you can freely copy thanks to the PSF license and it being rather short), then you should be doing __import__("some.module"); mod = sys.modules["some.module"]. That is the official, python-dev sanctioned solution to the problem (but only after you cannot use importlib).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜