问题:使用代码存储库时如何引用资源的相对路径
我们正在使用一个代码存储库,该代码存储库同时部署到Windows和Linux中-有时位于不同的目录中。项目内部的模块之一应如何引用项目中的非Python资源之一(CSV文件等)?
如果我们做类似的事情:
thefile=open('test.csv')
要么:
thefile=open('../somedirectory/test.csv')
仅当脚本从一个特定目录或目录的子集运行时,它才起作用。
我想做的是这样的:
path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)
可能吗?
We are working with a code repository which is deployed to both Windows and Linux – sometimes in different directories. How should one of the modules inside the project refer to one of the non-Python resources in the project (CSV files, etc.)?
If we do something like:
thefile=open('test.csv')
or:
thefile=open('../somedirectory/test.csv')
It will work only when the script is run from one specific directory, or a subset of the directories.
What I would like to do is something like:
path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)
Is it possible?
回答 0
尝试使用相对于当前文件路径的文件名。“ ./my_file”的示例:
fn = os.path.join(os.path.dirname(__file__), 'my_file')
在Python 3.4+中,您还可以使用pathlib:
fn = pathlib.Path(__file__).parent / 'my_file'
Try to use a filename relative to the current files path. Example for ‘./my_file’:
fn = os.path.join(os.path.dirname(__file__), 'my_file')
In Python 3.4+ you can also use pathlib:
fn = pathlib.Path(__file__).parent / 'my_file'
回答 1
如果您使用安装工具或分发(setup.py安装),则访问这些打包资源的“正确”方法似乎是使用package_resources。
以您的情况为例
import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")
当然,哪个读取资源,读取的二进制数据将是my_data的值
如果只需要文件名,也可以使用
resource_filename(package_or_requirement, resource_name)
例:
resource_filename("MyPackage","foo.dat")
优点是,即使是像鸡蛋一样的存档发行版,它也可以保证正常工作。
请参阅http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api
If you are using setup tools or distribute (a setup.py install) then the “right” way to access these packaged resources seem to be using package_resources.
In your case the example would be
import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")
Which of course reads the resource and the read binary data would be the value of my_data
If you just need the filename you could also use
resource_filename(package_or_requirement, resource_name)
Example:
resource_filename("MyPackage","foo.dat")
The advantage is that its guaranteed to work even if it is an archive distribution like an egg.
See http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api
回答 2
在Python中,路径是相对于当前工作目录的,在大多数情况下,该目录是您运行程序的目录。在当前的工作目录很可能不是同你的模块文件的目录,所以使用相对路径至当前的模块文件始终是一个不错的选择。
使用绝对路径应该是最好的解决方案:
import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
In Python, paths are relative to the current working directory, which in most cases is the directory from which you run your program. The current working directory is very likely not as same as the directory of your module file, so using a path relative to your current module file is always a bad choice.
Using absolute path should be the best solution:
import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
回答 3
我经常使用与此类似的东西:
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))
# ...
变量
__file__
保存您在其中编写该代码的脚本的文件名,因此您可以创建相对于脚本的路径,但仍使用绝对路径编写。它运行良好的原因有几个:
- 路径是绝对的,但仍然是相对的
- 该项目仍可以部署在相对的容器中
但是您需要注意平台兼容性-Windows的os.pathsep与UNIX不同。
I often use something similar to this:
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))
# ...
The variable
__file__
holds the file name of the script you write that code in, so you can make paths relative to script, but still written with absolute paths. It works quite well for several reasons:
- path is absolute, but still relative
- the project can still be deployed in a relative container
But you need to watch for platform compatibility – Windows’ os.pathsep is different than UNIX.
回答 4
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)
您还可以尝试规范化cwd
使用os.path.abspath(os.getcwd())
。更多信息在这里。
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)
You also try to normalize your cwd
using os.path.abspath(os.getcwd())
. More info here.
回答 5
您可以使用内置__file__
变量。它包含当前文件的路径。我将在您项目的根目录下的模块中实现getBaseOfProject。在那里,我将获得路径的一部分__file__
并将其返回。然后,可以在项目的任何地方使用此方法。
You can use the build in __file__
variable. It contains the path of the current file. I would implement getBaseOfProject in a module in the root of your project. There I would get the path part of __file__
and would return that. This method can then be used everywhere in your project.
回答 6
我在这里有点难过 想要将一些资源文件打包到wheel文件中并访问它们。打包过程是否使用清单文件,但是pip install不会安装它,除非它是子目录。希望这些精彩的镜头会有所帮助
├── 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
清单
recursive-include cnn_client/resources *
使用标准setup.py创建了一个weel。pip安装了wheel文件。安装后检查是否已安装资源。他们是
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中访问这些文件。从
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()
而且有效。
I got stumped here a bit. Wanted to package some resource files into a wheel file and access them. Did the packaging using manifest file, but pip install was not installing it unless it was a sub directory. Hoping these sceen shots will help
├── 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
MANIFEST.in
recursive-include cnn_client/resources *
Created a weel using standard setup.py . pip installed the wheel file.
After installation checked if resources are installed. They are
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
In tfclient.py to access these files. from
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()
And it works.
回答 7
我花了很长时间弄清楚这个问题的答案,但是我终于明白了(实际上很简单):
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的目录中,这看起来既快速又肮脏,但它的工作原理很像:)
I spent a long time figuring out the answer to this, but I finally got it (and it’s actually really simple):
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
This will append the relative path of your subfolder to the directories for python to look in
It’s pretty quick and dirty, but it works like a charm :)