目录
0x00 前言
最近在学习用python写一些小工具,过程免不了出现了寻找路径的功能,为了弄清这个问题我是彻底模糊了。因为python中获取路径的方法很多,获取的路径有相对路径,绝对路径,当前模块的路径,当前执行脚本的路径,到底哪一路径是我所需要的呢,为了解决这个问题,我是把自己搞迷糊了。
0x01 一些基础知识
这里需要稍微注意一下的是获取的目录有没有包含文件。
__file__
__file__ 是python中的特殊变量,用于获取当前模块的路径。
如果执行命令时使用绝对路径脚本,__file__
就是脚本的绝对路径。如果使用的是相对路径,__file__
就是脚本的相对路径。在交互式环境中,则会爆出异常。因为此时__file__
并未生成。
示例:free.py
print('__file__:',__file__)
可以看到效果如下
$ pwd
/Users/xy/big/xy/编程/python
$ python3 free.py
__file__: free.py
$ python3 ../python/free.py
__file__: ../python/free.py
sys.argv[0]
sys.argv 是一个列表对象,其中存储的是在命令行调用 Python 脚本时提供的“命令行参数”。
这个列表中的第一个参数即 sys.argv[0] 是被调用的脚本名称。
示例:free.py
import sys
print('sys.argv[0]:',sys.argv[0])
执行效果如下:
$ python3 free.py
sys.argv[0]: free.py
$ python3 ../python/free.py
sys.argv[0]: ../python/free.py
可以发现,在主文件中执行时,__file__和argv[0] 没有什么差异。
__file__ 和 argv[0] 的差异
但如果此时存在一个 test.py 文件,其中导入了 free.py 的代码。test.py 代码如下:
import free
free.py 代码如下:
import sys
print('__file__:',__file__)
print('sys.argv[0]:',sys.argv[0])
执行效果:
$ python3 test.py
__file__: /Users/xy/big/xy/编程/python/free.py
sys.argv[0]: test.py
$ python3 ../python/test.py
__file__: /Users/xy/big/xy/编程/python/free.py
sys.argv[0]: ../python/test.py
发现此时__file__ 变量获取了free模块文件的绝对路径,而sys.argv[0]仍然是当前执行文件的路径。
os.path.abspath()
os.path.dirname()
os.path.abspath(path)会返回path的绝对路径,和os.path.realpath()功能差不多,但推荐使用os.path.abspath(),获取的绝对路径更加纯粹一点。
os.path.dirname(path)会去掉path的文件,只会返回目录。os.path.dirname()只是单纯的操作字符串。
>>> path = 'free.py'
>>> path = os.path.abspath(path)
>>> path
'/Users/xy/big/xy/编程/python/free.py'
>>> os.path.dirname(path)
'/Users/xy/big/xy/编程/python'
os.getcwd()
“getcwd”实际上是“get the current working directory”的简写,顾名思义,也就是说这个函数的作用是“获取当前工作路径”。
示例:free.py 代码如下
import os
print(os.getcwd())
不同工作路径下的执行效果
$ python free.py
/Users/xy/big/xy/编程/python
$ python3 free.py
/Users/xy/big/xy/编程/python
$ cd ..
$ pwd
/Users/xy/big/xy/编程
$ python3 python/free.py
/Users/xy/big/xy/编程
sys.path[0]
该属性是一个由字符串组成的列表,其中各个元素表示的是 Python 搜索模块的路径,在程序启动期间被初始化。
其中第一个元素(也就是path[0]
)的值是最初调用 Python 解释器的脚本所在的绝对路径,所以在 import 同目录下的模块或包时就是从该目录搜索的。
示例:当前目录存在文件test.py,以及目录free目录下的dir.py文件。
test.py 的代码:
from free import dir
/free/dir.py 的代码:
import sys
print(sys.path[0])
执行结果如下:
$ python3 test.py
/Users/xy/big/xy/编程/python
$ python3 free/dir.py
/Users/xy/big/xy/编程/python/free
可以看到sys.path[0]的值为执行脚本的目录
0x02 获取常见的路径
获取关键文件的绝对路径
看了很多工具的框架大概如下,一个主文件scan.py,作为程序的入口,该文件会和其他代码文件夹放在同一个目录下。那么我们的目标就是找到scan.py所在的目录,这样我们才好寻找同目录下的其他文件,所以我们的很多操作都会以scan.py为轴。
$ ls
scan.py lib data plug ...
import 同目录下的其他文件,import 操作首先会在 sys.path[0] 中寻找当前文件的目录,那么可以利用 sys.path[0] 获取scan.py这个文件的绝对路径,方便引入其他文件
import sys
print('sys.path[0]:',sys.path[0])
不过我也看到很多使用下面的代码完成的。这样的需要保证最终执行的文件一定是scan.py
import sys
import os
root = os.path.abspath(sys.argv[0])
print('path:',os.path.dirname(root))
有的也会用__file__代替sys.argv[0],但一定保证__file__在scan.py中,这样在执行时,__file__才会返回scan.py的目录
import sys
import os
root = os.path.abspath(__file__)
print('path:',os.path.dirname(root))
暂时就记录这一个操作,后续补充。