是这样的, 今天下午写代码时遇到一个非常奇怪的bug, 与我原有对python的认知冲突, 实在不理解,所以花了许多时间才找到这个bug, 下面我把它用简单的方式重现出来, 大家讨论一下
首先, 在项目文件夹里面有以下几个文件:
test.pymodel/
Model.pymodel/
__init__.pymodel/content/
__init__.pytest.py中只有一句话: import model
然后model/
__init__.py 中的内容为:
print __file__ # 打印当前文件路径
from Model import ModelData
import content
其中print是为了调试看得, 另外两句一句都不能少
然后model/Model.py文件中的内容如下:
class Model:
pass
class ModelData:
pass
声明两个class而已
最后一个文件 model/content/
__init__.py 中的内容如下:
from .. import ModelData
整个代码的逻辑就是,test import了model, 而model又import了model/content
model/content 又 import ModelData, 而这个ModelData是在model/__init__.py中import的
看起来像是一个循环,其实并不是, 也没有矛盾, 代码能正常运行, 运行test.py文件后输出:
***/model/__init__.pyc
嗯,这是正常的, 然后我们把model/content/__init__.py的内容改为:
from Model import ModelData
然后再运行test.py, 会抛出以下异常:
from Model import ModelData
ImportError: No module named Model
嗯,这也是正常的, 因为第二种写法确实是错的
但是,bug来了, 第二种写法如果是在我这种特殊环境中运行就不正常了,
我用debian虚拟机写程序, 但是为了代码安全, 我把代码放到mac的文件系统上,然后通过共享文件夹的方式共享给debian系统。
然后我在debian下运行mac系统的python文件, 就不会抛出异常! 而出现以下的输出:
***/model/__init__.pyc
***/Model/__init__.pyc
尼玛, print语句运行了两次, 也就是说model被导入了两次! 并且第一次导入时初始化的数据会被第二次覆盖, 也就是这个特性导致我花了好几个小时来处理这个bug
也就是说, 如果你像我一样在区分大小写的系统上运行程序, 但是代码放在不区分大小写的系统上, 那么注意了, 像 from ABC import *** 这样的代码, 如果你的ABC和abc分别表示不同的意思, 那么就可能出现应该抛出异常但是没有抛出而引起其它bug的可能
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
https://www.v2ex.com/t/55738
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.