Python 包的引入顺序到底是怎样的?

文件结构如下:

$ tree .
.
├── main.py
├── os.py
└── platform.py

main.py:

import platform
import os
import sys
print('Now in main, Start`enter code here` to Exec following')
print(os.getcwd())
print(sys.modules['platform'].__file__)
print(platform.processor())

os.py:

print('Now in os.py module')

platform.py:

print('Now in platform.py module')

当我运行 python main.py,结果如下:

$ python main.py
Now in platform.py module
Now in main, Start to Exec following
/Users/michael/Code/00-Temp/pkg_import
/Users/michael/Code/00-Temp/pkg_import/platform.py
Traceback (most recent call last):
  File "main.py", line 9, in <module>
    print(platform.processor())
AttributeError: module 'platform' has no attribute 'processor'

问题1:osplatform 都是内置模块, 当 import os,默认走到了内置模块,但是 import platform, 却获取了同级目录下的 plarform,为何出现这个现象呢?

问题2:同样的脚本,我在 Pycharm 中直接运行 main.py ,却报这个错误:

/Users/michael/anaconda3/bin/python /Users/michael/Code/00-Temp/pkg_import/main.py
Now in os.py module
Fatal Python error: initsite: Failed to import the site module
Traceback (most recent call last):
  File "/Users/michael/anaconda3/lib/python3.7/site.py", line 570, in <module>
    main()
  File "/Users/michael/anaconda3/lib/python3.7/site.py", line 547, in main
    known_paths = removeduppaths()
  File "/Users/michael/anaconda3/lib/python3.7/site.py", line 126, in removeduppaths
    dir, dircase = makepath(dir)
  File "/Users/michael/anaconda3/lib/python3.7/site.py", line 91, in makepath
    dir = os.path.join(*paths)
AttributeError: module 'os' has no attribute 'path'

Process finished with exit code 1
阅读 7.8k
3 个回答

1.执行 python 就会把 os 引入进来了,不过是解释器做的,我们在程序中要使用之前,虽然还需要再显示的import os一下,但是其实解释器已经缓存过了!解释器启动的时候会导入一些标准库(注意是标准库,不是内置库)。而且,它缓存的时候,默认就是使用的built-in module,因为可能就默认了,不让你使用同名的模块吧

2.可以在修改 main.py 为:

import sys
print(sys.modules)

import platform
import os

print('Now in main, Start`enter code here` to Exec following')
print(os.getcwd())
print(sys.modules['platform'].__file__)
print(platform.processor())

这时候可以看到,里边已经有 os 缓存了,所以,即使下面再 import os,也不会重加载了。除非你后面在执行 import os之前先del sys.modules['os]',这时候,built-in module就会被同目录的 os.py 屏蔽了。

3.内置模块不是标准库,是指 sys.builtin_module_names输出的字符串元祖。解释器启动时确实会加载buit-in module,但是,执行print(sys.builtin_module_names)发现,os并不是built-in module。所以,解释器执行 python 文件时,不仅仅是加载了内置模块的!!!使用sys.modules可以看到实际启动时加载的所有模块。

The modules dictionary contains all loaded modules. The import statement checks this dictionary before it actually loads something from disk
sys.modules 包含了所有加载的模块。 import 语句在实际从磁盘上加载模块之前,会先去检查这个字典!

参考:

如果是python环境那么,导包会先从同级目录去找你导入的模块。如果找不到,回去python内置的第三方包去查找模块。完整的查找方式为:同级方法<--同级模块<--同级包<--第三方包

python 运行时会预转载一些module,你用sys.modules print 一下就知道了。如果已经加载就不会再有搜索一说了~

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏