os.getcwd()、sys.path[0]、sys.argv[0]和__file__的区别
要分清这几个的区别与使用条件,实际测试一下是最准确的。
设计测试方法:
一个主模块用来运行,一个子模块用来被主模块调用
主模块路径:
/Users/stephen/Documents/code/test_dir/01test
子模块路径:
/Users/stephen/Documents/code/test_dir/02test
运行模块的路径:
/Users/stephen/Documents/code/test_dir/01test/001_test
ok 现在编写两模块代码
- 子模块 submodule.py
import os
import sys
def child_test():
print('sub os.getcwd():{}'.format(os.getcwd()))
print('sub sys.path[0]:{}'.format(sys.path[0]))
print('sub sys.argv[0]:{}'.format(sys.argv[0]))
print('sub __file__:{}'.format(__file__))
if __name__ == '__main__':
chid_test()
- 主模块 mainmodule.py
import os
import sys
import submodule
def main():
print('main os.getcwd():{}'.format(os.getcwd()))
print('main sys.path[0]:{}'.format(sys.path[0]))
print('main sys.argv[0]:{}'.format(sys.argv[0]))
print('main __file__:{}'.format(__file__))
submodule.child_test()
if __name__ == '__main__':
main()
目录结构
├── 01test
│ ├── 001_test # 运行目录
│ └── mainmodule.py # 主模块
└── 02test
└── submodule.py # 被调用模块
ok 来看看结果
Traceback (most recent call last):
File "../mainmodule.py", line 3, in <module>
import submodule
ModuleNotFoundError: No module named 'submodule'
我去,出现了点小状况
原因是系统找不到该模块的路径,我们来人工添加一个路径
在主模块中前面添加
sys.path.append('/Users/stephen/Documents/code/test_dir/02test/')
再来试试 - -
结果如下:
main os.getcwd():/Users/stephen/Documents/code/test_dir/01test/001_test
main sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
main sys.argv[0]:../mainmodule.py
main __file__:../mainmodule.py
sub os.getcwd():/Users/stephen/Documents/code/test_dir/01test/001_test
sub sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
sub sys.argv[0]:../mainmodule.py
sub __file__:/Users/stephen/Documents/code/test_dir/02test/submodule.py
结合目录结构看就清楚了
├── 01test
│ ├── 001_test # 运行目录
│ └── mainmodule.py # 主模块
└── 02test
└── submodule.py # 被调用模块
-
os.getcwd()
指的是运行程序的目录 (绝对路径) -
sys.path[0]
主要模块的目录 (绝对路径) -
sys.argv[0]
运行模块时,pyhton 后面的参数 -
__file__
这个就有点奇怪了,主模块显示的相对路径,而被调用模块却用的绝对路径
__file__
还是有点疑虑,于是去 stack overflow(click to)看到了这句话,如下:
So, if you are outside the part of sys.path that contains the module, you'll get an absolute path. If you are inside the part of sys.path that contains the module, you'll get a relative path.
If you load a module in the current directory, and the current directory isn't in sys.path, you'll get an absolute path.
If you load a module in the current directory, and the current directory is in sys.path, you'll get a relative path.
意思大致是:
如果你(你所在的当前目录)不在sys.path
的范围里,你会得到绝对路径,反之,你会得到相对路径
如果你在当前目录加载模块,并且当前目录在sys.path
里, 你会得到相对路径。
对比上面的结果,符合。
不过我们还是应该再来验证下。我们把当前路径换到子模块下
├── 01test
│ ├── 001_test
│ └── mainmodule.py # 主模块
└── 02test # 当前目录
└── submodule.py # 被调用模块
结果如下:
main os.getcwd():/Users/stephen/Documents/code/test_dir/02test
main sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
main sys.argv[0]:../01test/mainmodule.py
main __file__:../01test/mainmodule.py
sub os.getcwd():/Users/stephen/Documents/code/test_dir/02test
sub sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
sub sys.argv[0]:../01test/mainmodule.py
sub __file__:/Users/stephen/Documents/code/test_dir/02test/submodule.py
是不是觉得有问题?幸亏我们测试了
突然想起我我运行mainmodule用的相对路径
像这样:
$ python ../01test/mainmodule.py
然后__file__
就是相对路径的,如果我们换成绝对路径呢?
$ python /Users/stephen/Documents/code/test_dir/01test/mainmodule.py
结果如下:
main os.getcwd():/Users/stephen/Documents/code/test_dir/02test
main sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
main sys.argv[0]:/Users/stephen/Documents/code/test_dir/01test/mainmodule.py
main __file__:/Users/stephen/Documents/code/test_dir/01test/mainmodule.py
sub os.getcwd():/Users/stephen/Documents/code/test_dir/02test
sub sys.path[0]:/Users/stephen/Documents/code/test_dir/01test
sub sys.argv[0]:/Users/stephen/Documents/code/test_dir/01test/mainmodule.py
sub __file__:/Users/stephen/Documents/code/test_dir/02test/submodule.py
soga!
终于弄清楚了,突然有种小兴奋啊
总结一下:
-
os.getcwd()
指的是当前目录,绝对路径 -
sys.path[0]
sys.path 指的是path,sys.path[0]为主模块目录的绝对路径,在模块运行的时候被自动添加进去 -
sys.argv[0]
就是你运行时 python 后面跟的参数 -
__file__
表示所在模块文件的路径,和系统找到该模块的方式有关,你是用绝对路径去加载该模块,那么__file__
就为绝对模块文件路径,如果你给系统提供相对路径去加载该模块,那么改文件路径为相对路径