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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40416072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 23:30:29  来源:igfitidea点击:

Reading file using relative path in python project

pythonpython-3.xiorelative-pathpython-import

提问by pbreach

Say I have a python project that is structured as follows:

假设我有一个结构如下的 python 项目:

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

__init__.py:

__init__.py

from .module import test

module.py:

module.py

import csv

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

main.py:

main.py

import package

print(package.test)

When I run main.pyI get the following error:

当我运行时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'

However, if I run module.pyfrom the packagedirectory I get no errors. So it seems that the relative path used in open(...)is only relative to where the originating file is being run from (i.e __name__ == "__main__")? I don't want to use absolute paths. What are some ways to deal with this?

但是,如果我module.pypackage目录运行,则不会出现任何错误。因此,似乎使用的相对路径open(...)仅与原始文件的运行位置有关(即__name__ == "__main__")?我不想使用绝对路径。有什么方法可以解决这个问题?

回答by spectras

Relative paths are relative to current working directory. If you do not your want your path to be, it must be absolute.

相对路径是相对于当前工作目录的。如果您不希望自己的路径成为,那么它必须是绝对的。

But there is an often used trick to build an absolute path from current script: use its __file__special attribute:

但是有一个常用的技巧可以从当前脚本构建绝对路径:使用它的__file__特殊属性:

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))

Note, from python 3.4, __file__is always absolute for imported modules and you can drop the os.path.abspathpart in this example.

请注意,从 python 3.4 开始,__file__对于导入的模块始终是绝对的,您可以os.path.abspath在此示例中删除该部分。

Better yet with python 3.4+, use the Path module as jpyams suggested in the comment below:

使用 python 3.4+ 更好,使用 Path 模块作为 jpyams 在下面的评论中建议:

from pathlib import Path

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

回答by aksh1618

For Python 3.4+:

对于 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)]

回答by kaspiotr

My Python version is Python 3.5.2and the solution proposed in the accepted answer didn't work for me. I've still were given an error

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

FileNotFoundError: [Errno 2] No such file or directory

when I was running my_script.pyfrom the terminal. Although it worked fine when I run it through Run/Debug Configurations from PyCharm IDE (PyCharm 2018.3.2 (Community Edition)).

当我my_script.py从终端运行时。尽管当我通过 PyCharm IDE(PyCharm 2018.3.2(社区版))的运行/调试配置运行它时它运行良好。

Solution:

解决方案

instead of using:

而不是使用:

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

as suggested in the accepted answer, I used:

正如接受的答案中所建议的那样,我使用了:

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

Explanation: Changing os.path.dirname(__file__)to os.path.dirname(os.path.abspath(__file__))solves the following problem:

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

When we run our script like that: python3 my_script.pythe __file__variable has a just a string value of "my_script.py" without path leading to that particular script. That is why method dirname(__file__)returns an empty string "". That is also the reson why my_path = os.path.abspath(os.path.dirname(__file__)) + some_rel_dir_pathis actually the same thing as my_path = some_rel_dir_path. Consequently FileNotFoundError: [Errno 2] No such file or directoryis given when trying to use openmethod because there is no directory like "some_rel_dir_path".

当我们运行脚本那样: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”这样的目录。

Running script from PyCharm IDE Running/Debug Configurations worked because it runs a command python3 /full/path/to/my_script.py(where "/full/path/to" is specified by us in "Working directory" variable in Run/Debug Configurations) instead of justpython3 my_script.pylike it is done when we run it from the terminal.

从 PyCharm IDE 运行/调试配置运行脚本之所以有效,是因为它运行一个命令python3 /full/path/to/my_script.py(其中“/full/path/to”是我们在运行/调试配置的“工作目录”变量中指定的),而不是python3 my_script.py像我们那样从终端运行它。

Hope that will be useful.

希望这将是有用的。