Python Import系统给粗心人设下的“陷阱”

编辑:光环大数据 来源: 互联网 时间: 2017-10-31 12:04 阅读:

  PythonImport系统给粗心人设下的“陷阱”。另一个常见的陷阱,特别对于初学者来说,是使用一个本地模块名导致覆盖了程序所依赖的标准库的或是第三方的包或者模块。一个特别意想不到的碰到这个陷阱的情况是对一个脚本使用这样的名字,因为这会结合之前“执行主模块两次”陷阱导致问题。例如,如果尝试学习更多关于Python的socket模块,你可能倾向于命名你的实验脚本为socket.py。事实证明这是一个坏主意,因为使用这样的名字意味着Python解释器可以不再去标准库中寻找真正的socket模块,因为当前目录里的这个socket模块挡住了去路:

旧的字节码文件陷阱

紧跟着之前小节的例子之后,假设我们决定通过重命名文件来修复我们错误的脚本名。在Python2中,我们会发现这仍然不起作用:

很明显,一些奇怪的事情发生了,因为我们看到在错误追踪中显示一个注释行出了问题。事实上,由我们之前错误的导入动作而缓存的字节码文件仍然存在,并且导致了这一问题,但是当Python试图在错误追踪中显示出错的源代码行时,它转而去标准库模块中寻找源代码行。删除旧的字节码文件可以让它正确运行:

这一特殊的陷阱在Python3.2以及之后的版本已经彻底去除了。在这些版本中,解释器可以区别独立的字节码文件(例如上文中的socket.pyc)和缓存的字节码文件(存储在自动生成的__pycache__目录下)。如果相应的源文件不存在,后者会被解释器忽略掉,所以上述的为源文件重命名如期工作了:

然而,需要注意的是,如果Python2留下了一个独立的字节码文件,混用Python2与Python3会导致问题:

如果你不是某个Python实现的核心开发人员,导入旧的字节码的问题很可能当重命名Python源文件时发生。而对于Python实现的开发人员,它则可能在我们使用负责首先产生字节码的编译器部件的任何时刻发生——这就是为什么CPython的Makefile中包含一个makepycremoval目标。

子模块被加入包命名空间的陷阱

许多人已经体验过了在仅仅导入了子模块所在的包而去使用该子模块时存在的问题了:

然而很少被人知的一件事是,当一个子模块在无论任何地方加载时,它会被自动地添加到包的全局命名空间中:

当你在一个__init__.py文件中导入或者定义一个同当前包的子模块拥有相同名字的值时,结果可能会更让你惊讶。如果子模块在导入或者定义了相同名字的值之后的任意位置被任何模块加载了,它将会在__init__.py的全局命名空间中覆盖已经导入的或者定义的名字。

更多的奇怪的陷阱

上面提到的都是一些平常的陷阱,但是还存在其他陷阱,尤其是如果你开始着手于扩展或者重写默认import系统的工作时。

最后我希望对这些增加一些细节描述:

__import__的怪异的签名

模块全局变量(__import__,__path__,__package__)的影响

3.3版本之前线程的问题

3.3版本之前默认的机器缺少对PEP302的支持

3.3版本之前命名空间包中的非合作的包的部分

sys.path[0]初始化变量

关于pickle,multiprocessing和主模块的问题的更多内容(参见PEP395)

__main__不总是一个顶级包(多亏了-m)

事实上,在导入过程中,模块是允许在sys.modules中替换他们自己的

__file__可能不指代一个实际文件系统的位置

自从3.2之后,你不能仅仅添加c或者o来获得缓存的字节码文件

 

  Python培训Python培训班Python培训机构,就选光环大数据!

  还不够过瘾?想学习更多?点击 http://hadoop.aura.cn/python/ 进行Python学习!


大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服

你可能也喜欢这些

在线客服咨询

领取资料

X
立即免费领取

请准确填写您的信息

点击领取
#第三方统计代码(模版变量) '); })();
'); })();