在 python 项目中使用相对路径读取文件
Reading file using relative path in python project
假设我有一个 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'
但是,如果我从 package
目录中 运行 module.py
,我不会收到任何错误。所以似乎 open(...)
中使用的相对路径仅相对于原始文件 运行 来自的位置(即 __name__ == "__main__"
)?我不想使用绝对路径。有什么方法可以解决这个问题?
相对路径是相对于current working directory。
如果你不希望你的路径是,它必须是绝对的。
但是有一个常用的技巧可以从当前脚本构建绝对路径:使用它的 __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 版本]
对于 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)]
我的 Python 版本是 Python 3.5.2 并且接受的答案中提出的解决方案对我不起作用。我仍然收到错误消息
FileNotFoundError: [Errno 2] No such file or directory
当我从终端 运行ning my_script.py
时。尽管当我通过 PyCharm IDE(PyCharm 2018.3.2(社区版))的 Run/Debug 配置时 运行 它工作正常。
解决方案:
而不是使用:
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__)
returns 一个空字符串“”。这也是 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 Running/Debug 的脚本配置有效,因为它 运行 是一个命令 python3 /full/path/to/my_script.py
(其中“/full/path/to" 是由我们在 Run/Debug 配置中的 "Working directory" 变量中指定的),而不是像我们从终端 运行 它时所做的那样只是 python3 my_script.py
。
希望有用。
尝试
with open(f"{os.path.dirname(sys.argv[0])}/data/test.csv", newline='') as f:
这对我有用。
with open('data/test.csv') as f:
当下面的代码起作用时,我惊呆了。
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
所以,我检查了 documentation,它说:
Changed in version 3.6: Accepts a path-like object.
An object representing a file system path. A path-like object is
either a str or...
我做了一个 little more digging 并且以下也有效:
with open("../FutureBookList/file.txt") as file:
data = file.read()
假设我有一个 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'
但是,如果我从 package
目录中 运行 module.py
,我不会收到任何错误。所以似乎 open(...)
中使用的相对路径仅相对于原始文件 运行 来自的位置(即 __name__ == "__main__"
)?我不想使用绝对路径。有什么方法可以解决这个问题?
相对路径是相对于current working directory。 如果你不希望你的路径是,它必须是绝对的。
但是有一个常用的技巧可以从当前脚本构建绝对路径:使用它的 __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 版本]
对于 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)]
我的 Python 版本是 Python 3.5.2 并且接受的答案中提出的解决方案对我不起作用。我仍然收到错误消息
FileNotFoundError: [Errno 2] No such file or directory
当我从终端 运行ning my_script.py
时。尽管当我通过 PyCharm IDE(PyCharm 2018.3.2(社区版))的 Run/Debug 配置时 运行 它工作正常。
解决方案:
而不是使用:
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__)
returns 一个空字符串“”。这也是 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 Running/Debug 的脚本配置有效,因为它 运行 是一个命令 python3 /full/path/to/my_script.py
(其中“/full/path/to" 是由我们在 Run/Debug 配置中的 "Working directory" 变量中指定的),而不是像我们从终端 运行 它时所做的那样只是 python3 my_script.py
。
希望有用。
尝试
with open(f"{os.path.dirname(sys.argv[0])}/data/test.csv", newline='') as f:
这对我有用。
with open('data/test.csv') as f:
当下面的代码起作用时,我惊呆了。
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
所以,我检查了 documentation,它说:
Changed in version 3.6: Accepts a path-like object.
An object representing a file system path. A path-like object is either a str or...
我做了一个 little more digging 并且以下也有效:
with open("../FutureBookList/file.txt") as file:
data = file.read()