Python在import时遇到的惨案

    
    最近使用基于python语言的django框架开发web相关的应用,但是在访问页面的时候会不定时的报错,import导入报错


 经过近1个月的观察发现有这么几个特性:不知道什么时候会触发,但是一旦触发,就一直存在这个问题只要重启web服务或者调试 问题马上就能解决。

   咋一看:难道是django框架不稳定?
   不要轻易怀疑框架的问题,绝大多数情况下是自己的问题。


 查看一下 __import__的描述:

__import__(name[, globals[, locals[, fromlist[, level]]]])

Note

This is an advanced function that is not needed in everyday Python programming.

This function is invoked by the import statement. It can be replaced (by importing the __builtin__ module and assigning to__builtin__.__import__) in order to change semantics of the import statement, but nowadays it is usually simpler to use import hooks (see PEP 302). Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime.

The function imports the module name, potentially using the given globals and locals to determine how to interpret the name in a package context. The fromlist gives the names of objects or submodules that should be imported from the module given by name. The standard implementation does not use its locals argument at all, and uses its globals only to determine the package context of the importstatement.

level specifies whether to use absolute or relative imports. The default is -1 which indicates both absolute and relative imports will be attempted. 0 means only perform absolute imports. Positive values for level indicate the number of parent directories to search relative to the directory of the module calling __import__().

When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned.

For example, the statement import spam results in bytecode resembling the following code:

spam = __import__('spam', globals(), locals(), [], -1)
The statement import spam.ham results in this call:

spam = __import__('spam.ham', globals(), locals(), [], -1)
Note how __import__() returns the toplevel module here because this is the object that is bound to a name by the import statement.


    从上面的doc我们可以学到:
    涉及的2个最重要的点:
    这有个非常关键的参数 globals 默认为 globals()内置函数返回的全局的对象。
    sys.modules 保存在 global()返回的sys对象中。
    对sys.modules有如下的特性:
    当导入新的模块,它们加入到 sys.modules 中。这就解释了为什么第二次导入相同的模块时非常的快:Python 已经在 sys.modules 中装入和缓冲了,所以第二次导入仅仅对字典做了一个查询。
一旦给出任何以前导入过的模块名(以字符串方式),通过 sys.modules 字典,你可以得到对模块本身的一个引用。

    所以,使用python动态import的时候,千万要小心不要使用相同的模块名字,最好也不要使用相同的类名。