我有一个具有以下目录结构的Python项目:
project/ project/src/ project/src/somecode.py project/src/mypackage/mymodule.py project/src/resources/ project/src/resources/datafile1.txt
在mymodule.py中,我有一个类(我们称之为“MyClass”),需要加载datafile1.txt。当我这样做时,这种方式有效:
open(“../ resources / datafile1.txt”)
假设创建MyClass实例的代码是从somecode.py。
运行的但问题是我对mymodule.py进行了单元测试,这些测试是在该文件中定义的,如果我保留上面描述的相对路径名,则单元测试代码会爆炸,因为现在代码是从project / src运行的/ mypackage而不是project / src,相对文件路径无法正确解析。
有关最佳实践类型方法的任何建议可以解决此问题吗?如果我将我的测试用例移动到project / src,它会使主要源文件夹与测试用例混乱。
答案 0 :(得分:7)
我通常使用它从模块中获取相对路径。从未尝试过单位测试。
import os
print(os.path.join(os.path.dirname(__file__),
'..',
'resources'
'datafile1.txt'))
注意:..技巧很有效,但是如果你改变你的目录结构,你需要更新那个部分。
答案 1 :(得分:3)
除了上述答案外,我想添加一些Python 3技巧来使您的测试更加简洁。
借助pathlib库,您可以在测试中显式导入资源。它甚至处理Unix(/)和Windows()之间的分隔符差异。
假设我们有一个这样的文件夹结构:
`-- tests
|-- test_1.py <-- You are here !
|-- test_2.py
`-- images
|-- fernando1.jpg <-- You want to import this image !
`-- fernando2.jpg
您位于test_1.py
文件中,并且想要导入fernando1.jpg
。在pathlib库的帮助下,您可以使用面向对象的逻辑来读取测试资源,如下所示:
from pathlib import Path
current_path = Path(os.path.dirname(os.path.realpath(__file__)))
image_path = current_path / "images" / "fernando1.jpg"
with image_path.open(mode='rb') as image :
# do what you want with your image object
但是实际上有一些便捷的方法可以使您的代码比mode='rb'
更明确,例如:
image_path.read_bytes() # Which reads bytes of an object
text_file_path.read_text() # Which returns you text file content as a string
然后去!
答案 2 :(得分:2)
在包含Python脚本的每个目录中,放置一个知道层次结构根路径的Python模块。它可以使用相对路径定义单个全局变量。在每个脚本中导入此模块。 Python首先搜索当前目录,因此它将始终使用当前目录中模块的版本,该版本将具有指向当前目录根目录的相对路径。然后使用它来查找其他文件。例如:
# rootpath.py
rootpath = "../../../"
# in your scripts
from rootpath import rootpath
datapath = os.path.join(rootpath, "src/resources/datafile1.txt")
如果您不想在每个目录中添加其他模块,可以使用以下方法:
将一个sentinel文件放在目录结构的顶层,例如thisisthetop.txt
。让Python脚本向上移动目录层次结构,直到找到此文件。写下相对于该目录的所有路径名。
可能您在项目目录中已有的某个文件可用于此目的(例如,在找到src
目录之前继续向上移动),或者您可以以这样的方式命名项目目录显而易见。
答案 3 :(得分:0)
文件路径将相对于您最初调用的脚本。我建议您将相对路径作为参数传递给MyClass。这样,您可以使用不同的路径,具体取决于调用MyClass的脚本。