python获取文件路径小结

业务线最近遇到一个问题,缘由是以下代码导致的

1
2
3
4
def get_work_dir():
work_dir = os.path.split(os.path.realpath(sys.argv[0]))[0]
sdk = os.path.join(work_dir, "certificate/license-sdk")
....

整体来讲,就是在获取当前文件执行路径的时候出了问题。单独运行py文件和用uwsgi运行py文件,及用gunicorn运行py文件,这种方式获取的路径在代码运行的过程中是不一致的。为了验证上述问题,做如下测试:

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import os
import sys
from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
print("------------")
print(sys.argv)
print(os.path.realpath(sys.argv[0]))
#print(os.getcwd())
#print(os.path.abspath('.'))
print("------------")
return 'Hello World!'


if __name__ == '__main__':
app.run()
  1. 单独启动flask项目,返回结果如下:
1
2
['/Users/zyy/Downloads/workspace/python3/learn/.venv/lib/python3.6/site-packages/flask/__main__.py', 'run']
/Users/zyy/Downloads/workspace/python3/learn/.venv/lib/python3.6/site-packages/flask/__main__.py
  1. 通过uwsgi启动项目,
1
2
3
4
5
6
wsgi --socket 0.0.0.0:5000 --protocol=http -p 1  --set foo=bar -w run:app

返回结果如下:

['uwsgi']
/Users/zyy/Downloads/workspace/python3/learn/uwsgi
  1. 通过gunicorn启动项目
1
2
3
4
5
6
gunicorn -w 1 -b 127.0.0.1:5000 run:app

返回结果如下:

['/Users/zyy/Downloads/workspace/python3/learn/.venv/bin/gunicorn', '-w', '1', '-b', '127.0.0.1:5000', 'run:app']
/Users/zyy/Downloads/workspace/python3/learn/.venv/bin/gunicorn
  1. 小结

对比来看,三种方式启动后获取的文件路径都不一样,所以当通过uwsgi替换为gunicorn的时候,上述代码会出现问题。为了避免出现问题,可以通过其他方式来获取当前项目的执行路径。比如可以通过以下方式来获取项目执行路径。

1
os.getcwd()

获取当前路径

  1. 使用sys.argv[0]
1
2
import sys
print sys.argv[0]
  1. os模块
1
2
3
4
5
print(os.getcwd()) #获取当前工作目录路径
print(os.path.abspath('.')) #获取当前工作目录路径
print(os.path.abspath('test.txt')) #获取当前目录文件下的工作目录路径
print(os.path.abspath('..')) #获取当前工作的父目录 !注意是父目录路径
print(os.path.abspath(os.curdir)) #获取当前工作目录路径
  1. 改变当前路径

使用: os.chdir(path)

比如, 如果当前目录在 ‘E:’ 下面, 然后进入E 下面的files 文件 可以使用 os.chdir(E:\files).之后,使用比如 test1 = open(‘file1.txt’), 打开的文件会是在这个 ‘E:\files’ 目录下的文件,而不是 ‘E’ 下的文件。

  1. 组合路径返回
1
os.path.join('file1','file2','file3')

合并得到路径 file1/file2/file3

1
2
3
4
>>> print os.path.join('E:', 'file1', 'file2')
E:/file1/file2
>>> print os.path.join('/home', '/home/file1/', '/home/file1/file2/')
/home/file1/file2/

获得当前目录下所有文件

os.walk() 用于在目录树种游走输出目录中的文件名字,向上或下

1
2
3
4
5
6
7
8
9
10
11
12
13
语法
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])

参数:
top -- 根目录下的每一个文件夹(包含它自己), 产生3-元组 (dirpath, dirnames, filenames)【文件夹路径,
文件夹名字, 文件名】。

topdown --可选,为True或者没有指定, 一个目录的的3-元组将比它的任何子文件夹的3-元组先产生 (目录自上而下)。
如果topdown为 False, 一个目录的3-元组将比它的任何子文件夹的3-元组后产生 (目录自下而上)。

onerror -- 可选,是一个函数; 它调用时有一个参数, 一个OSError实例。报告这错误后,继续walk,或者抛出exception终止walk。

followlinks -- 设置为 true,则通过软链接访问目录。

测试代码如下:

1
2
3
4
5
6
7
def file_name(file_dir):
for root, dirs, files in os.walk(file_dir):
print("-----------")
print(root) # os.walk()所在目录
print(dirs) # os.walk()所在目录的所有目录名
print(files) # os.walk()所在目录的所有非目录文件名
print(" ")