在Python项目中使用相对路径读取文件

问题描述 投票:0回答:6

假设我有一个Python项目,其结构如下:

project
    /data
        test.csv
    /package
        __init__.py
        module.py
    main.py

__init__.py

from .module import test

module.py

import csv

with open("..data/test.csv") as f:
    test = [line for line in csv.reader(f)]

main.py

import package

print(package.test)

当我运行

main.py
时,我收到以下错误:

 C:\Users\Patrick\Desktop\project>python main.py
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import package
  File "C:\Users\Patrick\Desktop\project\package\__init__.py", line 1, in <module>
    from .module import test
  File "C:\Users\Patrick\Desktop\project\package\module.py", line 3, in <module>
    with open("../data/test.csv") as f:
FileNotFoundError: [Errno 2] No such file or directory: '../data/test.csv'

但是,如果我从

module.py
目录运行
package
,我不会收到任何错误。因此,
open(...)
中使用的相对路径似乎仅相对于原始文件的运行位置(即
__name__ == "__main__"
)?仅使用相对路径如何处理这个问题?

python python-3.x io relative-path python-import
6个回答
217
投票

相对路径是相对于当前工作目录的。 如果您不希望路径是相对的,则它必须是绝对的。

但是有一个常用的技巧可以从当前脚本构建绝对路径:使用其

__file__
特殊属性:

from pathlib import Path

path = Path(__file__).parent / "../data/test.csv"
with path.open() as f:
    test = list(csv.reader(f))

这需要 python 3.4+(对于 pathlib 模块)。

如果您仍然需要支持旧版本,您可以通过以下方式获得相同的结果:

import csv
import os.path

my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "../data/test.csv")
with open(path) as f:
    test = list(csv.reader(f))

[2020编辑:python3.4+现在应该成为常态,所以我首先移动了受jpyams评论启发的pathlib版本]


47
投票

对于 Python 3.4+:

import csv
from pathlib import Path

base_path = Path(__file__).parent
file_path = (base_path / "../data/test.csv").resolve()

with open(file_path) as f:
    test = [line for line in csv.reader(f)]

5
投票

这对我有用。

with open('data/test.csv') as f:

 

4
投票

我的Python版本是Python 3.5.2,接受的答案中提出的解决方案对我不起作用。我仍然遇到错误

FileNotFoundError:[Errno 2]没有这样的文件或目录

当我从终端运行

my_script.py
时。尽管当我通过 PyCharm IDE(PyCharm 2018.3.2(社区版))中的运行/调试配置运行它时,它工作得很好。

解决方案

而不是使用:

my_path = os.path.abspath(os.path.dirname(__file__)) + some_rel_dir_path

按照已接受的答案中的建议,我使用了:

my_path = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) + some_rel_dir_path

解释

os.path.dirname(__file__)
更改为
os.path.dirname(os.path.abspath(__file__))
解决了以下问题:

当我们像这样运行脚本时:

python3 my_script.py
__file__
变量只有一个字符串值“my_script.py”,没有指向该特定脚本的路径。这就是方法
dirname(__file__)
返回空字符串“”的原因。这也是为什么
my_path = os.path.abspath(os.path.dirname(__file__)) + some_rel_dir_path
实际上与
my_path = some_rel_dir_path
相同的原因。因此,当尝试使用
FileNotFoundError: [Errno 2] No such file or directory
方法时,会给出
open
,因为没有像“some_rel_dir_path”这样的目录。

从 PyCharm IDE 运行/调试配置运行脚本之所以有效,是因为它运行命令

python3 /full/path/to/my_script.py
(其中“/full/path/to”由我们在运行/调试配置中的“工作目录”变量中指定),而不是仅仅
python3 my_script.py 
就像我们从终端运行它时完成的一样。


1
投票

尝试

with open(f"{os.path.dirname(sys.argv[0])}/data/test.csv", newline='') as f:

0
投票

当以下代码起作用时,我感到很惊讶。

import os

for file in os.listdir("../FutureBookList"):
    if file.endswith(".adoc"):
        filename, file_extension = os.path.splitext(file)
        print(filename)
        print(file_extension)
        continue
    else:
        continue

所以,我检查了文档,它说:

3.6 版更改:接受类似路径的对象。

类路径对象:

代表文件系统路径的对象。类似路径的对象是 要么是 str 要么...

我做了一些更多的挖掘,以下内容也有效:

with open("../FutureBookList/file.txt") as file:
   data = file.read()
© www.soinside.com 2019 - 2024. All rights reserved.