How to refer to relative paths of resources when working with a code repository in Python
我们正在使用一个同时部署到Windows和Linux的代码存储库——有时在不同的目录上。项目中的一个模块应该如何引用项目中的一个非python资源(csv文件等)?
如果我们做类似的事情:
1 | thefile=open('test.csv') |
或:
1 | thefile=open('../somedirectory/test.csv') |
只有当脚本从一个特定目录或目录的一个子集运行时,它才会工作。
我想做的是:
1 2 | path=getBasePathOfProject()+'/somedirectory/test.csv' thefile=open(path) |
这条路对吗?有可能吗?
尝试使用相对于当前文件路径的文件名。'/my_file'示例:
1 | fn = os.path.join(os.path.dirname(__file__), 'my_file') |
在python 3.4+中,还可以使用pathlib:
1 | fn = pathlib.Path(__file__).parent / 'my_file' |
如果您使用安装工具或分发(setup.py安装),那么访问这些打包资源的"正确"方法似乎是使用包资源。
在你的例子中,例子是
1 2 | import pkg_resources my_data = pkg_resources.resource_string(__name__,"foo.dat") |
哪个读取资源和读取的二进制数据将是我的数据的值?
如果您只需要文件名,也可以使用
1 | resource_filename(package_or_requirement, resource_name) |
例子:
1 | resource_filename("MyPackage","foo.dat") |
其优势在于,即使是像鸡蛋一样的档案分发,它也能保证工作正常。
请参阅http://packages.python.org/distribute/pkg_resources.html resourcemanager api
我经常用类似的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import os DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir')) # if you have more paths to set, you might want to shorten this as here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x)) DATA_DIR = here('datadir') pathjoin = os.path.join # ... # later in script for fn in os.listdir(DATA_DIR): f = open(pathjoin(DATA_DIR, fn)) # ... |
变量
1 | __file__ |
保留编写该代码的脚本的文件名,以便可以相对于脚本创建路径,但仍使用绝对路径编写。它工作得很好,原因有几个:
- 路径是绝对的,但仍然是相对的
- 项目仍然可以部署在相对容器中
但您需要注意平台兼容性-Windows的os.pathsep与Unix不同。
在python中,路径是相对于当前工作目录的,在大多数情况下,这是运行程序的目录。当前工作目录很可能与模块文件的目录不同,因此使用相对于当前模块文件的路径总是一个错误的选择。
使用绝对路径应该是最佳解决方案:
1 2 3 | import os package_dir = os.path.dirname(os.path.abspath(__file__)) thefile = os.path.join(package_dir,'test.cvs') |
1 2 3 4 | import os cwd = os.getcwd() path = os.path.join(cwd,"my_file") f = open(path) |
您还尝试使用
您可以使用内置的
我在这里受了点挫折。想要将一些资源文件打包成一个轮子文件并访问它们。使用清单文件进行打包,但PIP安装没有安装它,除非它是子目录。希望这些权杖能有帮助
1 2 3 4 5 6 7 8 | ├── cnn_client │ ├── image_preprocessor.py │ ├── __init__.py │ ├── resources │ │ ├── mscoco_complete_label_map.pbtxt │ │ ├── retinanet_complete_label_map.pbtxt │ │ └── retinanet_label_map.py │ ├── tf_client.py |
在
1 | recursive-include cnn_client/resources * |
使用standard setup.py创建了一个WEEL。PIP安装了车轮文件。安装后检查是否安装了资源。他们是
1 2 3 4 5 | ls /usr/local/lib/python2.7/dist-packages/cnn_client/resources mscoco_complete_label_map.pbtxt retinanet_complete_label_map.pbtxt retinanet_label_map.py |
在tfclient.py中访问这些文件。从
1 2 3 4 | templates_dir = os.path.join(os.path.dirname(__file__), 'resources') file_path = os.path.join(templates_dir, \ 'mscoco_complete_label_map.pbtxt') s = open(file_path, 'r').read() |
它起作用了。
我花了很长时间想清楚这个问题的答案,但最终我得到了它(实际上很简单):
1 2 3 4 5 6 | import sys import os sys.path.append(os.getcwd() + '/your/subfolder/of/choice') # now import whatever other modules you want, both the standard ones, # as the ones supplied in your subfolders |
这将把子文件夹的相对路径附加到要让python查找的目录中。它很快又脏,但它的作用就像一个魅力:)