我正在构建一个简单的助手脚本,用于将代码库中的两个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我有一个相对路径从脚本,但当我调用脚本,它把它作为一个相对于当前工作目录的路径。是否有一种方法来指定这个相对url是来自脚本的位置?


当前回答

我不确定这是否适用于一些旧版本,但我相信Python 3.3具有原生相对路径支持。

例如,下面的代码应该在与python脚本相同的文件夹中创建一个文本文件:

open("text_file_name.txt", "w+t")

(注意,如果是相对路径,开头不应该有正斜杠或反斜杠)

其他回答

例子


下面是一个用Python '3.9.5 '测试的例子:

您的当前目录:'c:\project1\code\' 你想要访问以下文件夹:'c:\project1\dataset\train\'。 然后您可以使用以下地址访问该文件夹:“../dataset/train/”

参考文献


如果你想了解更多关于Python中路径的信息,请阅读以下内容:

Pep - 355 Pep - 519

我不确定这是否适用于一些旧版本,但我相信Python 3.3具有原生相对路径支持。

例如,下面的代码应该在与python脚本相同的文件夹中创建一个文本文件:

open("text_file_name.txt", "w+t")

(注意,如果是相对路径,开头不应该有正斜杠或反斜杠)

根据其他建议和pathlib文档,一个简单(但不理想)的解决方案如下(假设我们需要引用的文件是Test/data/users.csv):

# Current file location: Tests/src/long/module/subdir/some_script.py
from pathlib import Path

# back to Tests/
PROJECT_ROOT = Path(__file__).parents[4]
# then down to Test/data/users.csv
CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'  

with CSV_USERS_PATH.open() as users:
    print(users.read())

这是可行的,但看起来有点奇怪,因为如果您移动some_script.py,到项目根目录的路径可能会改变(因此我们需要更改父目录[4]部分)。

我想我找到了一个更好的解决方案,基于同样的想法。 我们将使用path .py文件来存储项目的根目录,与根目录相比,这个文件将保持在相同的位置。

Tests
├── data
│  └── users.csv
└── src
   ├── long
   │  └── module
   │     └── subdir
   │        └── some_script.py
   ├── main.py
   └── paths.py

path .py的唯一职责是提供PROJECT_ROOT:

from pathlib import Path

PROJECT_ROOT = Path(__file__).parents[1]

所有脚本现在都可以使用路径。PROJECT_ROOT表示从项目根开始的绝对路径。例如,在src/long/module/subdir/some_script.py中,我们可以有:

from paths import PROJECT_ROOT

CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'

def hello():
    with CSV_USERS_PATH.open() as f:
        print(f.read())

一切都如你所料:

~/Tests/src/$ python main.py

/Users/cglacet/Tests/data/users.csv
hello, user

~/Tests/$ python src/main.py

/Users/cglacet/Tests/data/users.csv
hello, user

main.py脚本就是:

from long.module.subdir import some_script

some_script.hello()

而不是使用

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

在公认的答案中,使用它会更健壮:

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

因为使用__file__将返回加载模块的文件,如果它是从一个文件中加载的,所以如果从其他地方调用带有脚本的文件,则返回的目录将不正确。

这些答案提供了更多的细节:https://stackoverflow.com/a/31867043/5542253和https://stackoverflow.com/a/50502/5542253

最重要命令的摘要

>>> import os
>>> os.path.join('/home/user/tmp', 'subfolder')
'/home/user/tmp/subfolder'
>>> os.path.normpath('/home/user/tmp/../test/..')
'/home/user'
>>> os.path.relpath('/home/user/tmp', '/home/user')
'tmp'
>>> os.path.isabs('/home/user/tmp')
True
>>> os.path.isabs('/tmp')
True
>>> os.path.isabs('tmp')
False
>>> os.path.isabs('./../tmp')
False
>>> os.path.realpath('/home/user/tmp/../test/..') # follows symbolic links
'/home/user'

详细的描述可以在文档中找到。 这些是linux路径。Windows的工作原理与此类似。