Python中的相对路径

新手上路,请多包涵

我正在为工作构建一个简单的帮助脚本,它将我们代码库中的几个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我确实有来自脚本的相对路径,但是当我调用脚本时,它会将其视为相对于当前工作目录的路径。有没有办法指定这个相对 url 来自脚本的位置?

原文由 baudtack 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 729
2 个回答

在包含脚本的文件中,您想要执行以下操作:

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

这将为您提供要查找的文件的绝对路径。请注意,如果您使用的是 setuptools,您可能应该改用它的 包资源 API

更新:我在这里回复评论,以便粘贴代码示例。 :-)

我是否认为 __file__ 并不总是可用(例如,当您直接运行文件而不是导入文件时)?

当您提到直接运行文件时,我假设您的意思是 __main__ 脚本。如果是这样,我的系统上似乎不是这种情况(OS X 10.5.7 上的 python 2.5.1):

 #foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

但是,我知道在 C 扩展上有一些 __file__ 的怪癖。例如,我可以在我的 Mac 上执行此操作:

 >>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

但是,这会在我的 Windows 机器上引发异常。

原文由 Jason Baker 发布,翻译遵循 CC BY-SA 4.0 许可协议

现在是 2018 年,Python 早已发展到 __future__ 很久以前。 So how about using the amazing pathlib coming with Python 3.4 to accomplish the task instead of struggling with os , os.path , glob , shutil

所以我们这里有 3 条路径(可能重复):

  • mod_path :这是 简单帮助脚本 的路径
  • src_path :其中包含 _几个等待复制的模板文件_。
  • cwd : _当前目录_,这些模板文件的目的地。

问题是: 我们没有 src_path 的完整路径,只知道它是 mod_path 的相对路径

现在让我们用神奇的 pathlib 来解决这个问题:

 # Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

未来,就这么简单。


此外,我们可以使用 pathlib 选择、检查和复制/移动这些模板文件:

 if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)

原文由 YaOzI 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题