[英]Reading file using relative path in python project
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.py
I 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.py
from the package
directory I get no errors.但是,如果我从
package
目录运行module.py
,则不会出现任何错误。 So it seems that the relative path used in open(...)
is only relative to where the originating file is being run from (ie __name__ == "__main__"
)?因此,似乎
open(...)
使用的相对路径仅与运行原始文件的位置有关(即__name__ == "__main__"
)? I don't want to use absolute paths.我不想使用绝对路径。 What are some ways to deal with this?
有什么方法可以解决这个问题?
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__
特殊属性:
from pathlib import Path
path = Path(__file__).parent / "../data/test.csv"
with path.open() as f:
test = list(csv.reader(f))
This requires python 3.4+ (for the pathlib module).这需要 python 3.4+(对于pathlib模块)。
If you still need to support older versions, you can get the same result with:如果你仍然需要支持旧版本,你可以得到相同的结果:
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 edit: python3.4+ should now be the norm, so I moved the pathlib version inspired by jpyams' comment first] [ 2020 编辑: python3.4+ 现在应该是常态,所以我首先移动了受 jpyams 评论启发的 pathlib 版本]
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)]
这对我有用。
with open('data/test.csv') as f:
My Python version is Python 3.5.2 and the solution proposed in the accepted answer didn't work for me.我的 Python 版本是Python 3.5.2 ,接受的答案中提出的解决方案对我不起作用。 I've still were given an error
我仍然收到错误
FileNotFoundError: [Errno 2] No such file or directory
when I was running my_script.py
from the terminal.当我从终端运行
my_script.py
。 Although it worked fine when I run it through Run/Debug Configurations from PyCharm IDE (PyCharm 2018.3.2 (Community Edition)).尽管当我通过 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.py
the __file__
variable has a just a string value of "my_script.py" without path leading to that particular script.当我们像这样运行我们的脚本时:
python3 my_script.py
__file__
变量只有一个字符串值“my_script.py”,没有通向该特定脚本的路径。 That is why method dirname(__file__)
returns an empty string "".这就是方法
dirname(__file__)
返回空字符串 "" 的原因。 That is also the reson why my_path = os.path.abspath(os.path.dirname(__file__)) + some_rel_dir_path
is actually the same thing as my_path = some_rel_dir_path
.这也是为什么
my_path = os.path.abspath(os.path.dirname(__file__)) + some_rel_dir_path
实际上与my_path = some_rel_dir_path
相同的my_path = some_rel_dir_path
。 Consequently FileNotFoundError: [Errno 2] No such file or directory
is given when trying to use open
method because there is no directory like "some_rel_dir_path".因此
FileNotFoundError: [Errno 2] No such file or directory
尝试使用open
方法时FileNotFoundError: [Errno 2] No such file or directory
因为没有像“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 just python3 my_script.py
like 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.希望这将是有用的。
尝试
with open(f"{os.path.dirname(sys.argv[0])}/data/test.csv", newline='') as f:
I was thundered when the following code worked.当以下代码起作用时,我感到震惊。
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
So, I checked the documentation and it says:所以,我检查了文档,它说:
Changed in version 3.6: Accepts a path-like object.
在 3.6 版更改: 接受一个类似路径的对象。
An object representing a file system path.
表示文件系统路径的对象。 A path-like object is either a str or...
类似路径的对象是 str 或...
I did a little more digging and the following also works:我做了更多的挖掘,以下也有效:
with open("../FutureBookList/file.txt") as file:
data = file.read()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.