使用python的操作系统。路径,如何往上一个目录?

我最近把Django从v1.3.1升级到了v1.4。

在我的旧settings.py我有

TEMPLATE_DIRS = (
os.path.join(os.path.dirname( __file__ ), 'templates').replace('\\', '/'),
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)

这将指向/Users/hobbes3/Sites/mysite/templates,但是因为Django v1.4将project文件夹移到了app文件夹的同一层,我的settings.py文件现在在/Users/hobbes3/Sites/mysite/mysite/而不是/Users/hobbes3/Sites/mysite/

所以实际上我的问题是双重的

  1. 我如何使用os.path来查看从__file__上一级的目录。换句话说,我希望/Users/hobbes3/Sites/mysite/mysite/settings.py使用相对路径找到/Users/hobbes3/Sites/mysite/templates
  2. 我应该保持template文件夹(其中有跨应用程序模板,如adminregistration等)在项目/User/hobbes3/Sites/mysite级别或/User/hobbes3/Sites/mysite/mysite?
318374 次浏览
os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))

至于模板文件夹应该放在哪里,我不知道,因为Django 1.4刚刚出来,我还没有看过它。你可能应该问另一个关于SE的问题来解决这个问题。

你也可以使用normpath来清理路径,而不是abspath。然而,在这种情况下,Django希望使用绝对路径而不是相对路径。

为了跨平台兼容性,使用os.pardir代替'..'

要获取一个文件的文件夹,只需使用:

os.path.dirname(path)

要创建一个文件夹,再次使用os.path.dirname即可

os.path.dirname(os.path.dirname(path))

你可能想检查__file__是否是符号链接:

if os.path.islink(__file__): path = os.readlink (__file__)

你想要的就是:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )
from os.path import dirname, realpath, join
join(dirname(realpath(dirname(__file__))), 'templates')

更新:

如果你碰巧通过符号链接“复制”settings.py, @forivall的答案更好:

~user/
project1/
mysite/
settings.py
templates/
wrong.html


project2/
mysite/
settings.py -> ~user/project1/settings.py
templates/
right.html

上面的方法将“看到”wrong.html,而@forivall的方法将看到right.html

在没有符号联系的情况下,这两个答案是相同的。

对我这样的偏执狂来说,我更喜欢这个

TEMPLATE_DIRS = (
__file__.rsplit('/', 2)[0] + '/templates',
)

就我个人而言,我倾向于函数方法

def get_parent_dir(directory):
import os
return os.path.dirname(directory)


current_dirs_parent = get_parent_dir(os.getcwd())
我认为最简单的方法就是重用dirname() 所以你可以调用

os.path.dirname(os.path.dirname( __file__ ))

如果你的文件在/Users/hobbes3/Sites/mysite/templates/method.py

返回"/Users/hobbes3/Sites/mysite"

这在其他情况下很有用当你想往上移动x个文件夹时。只需要运行walk_up_folder(path, 6)来上升6个文件夹。

def walk_up_folder(path, depth=1):
_cur_depth = 1
while _cur_depth < depth:
path = os.path.dirname(path)
_cur_depth += 1
return path

如果你使用的是Python 3.4或更新版本,上移多个目录的方便方法是pathlib:

from pathlib import Path


full_path = "path/to/directory"
str(Path(full_path).parents[0])  # "path/to"
str(Path(full_path).parents[1])  # "path"
str(Path(full_path).parents[2])  # "."

n文件夹…运行up(n)

import os


def up(n, nth_dir=os.getcwd()):
while n != 0:
nth_dir = os.path.dirname(nth_dir)
n -= 1
return nth_dir

当然:只需使用os.chdir(..)即可。

使用os.path,我们可以像这样往上走一个目录

one_directory_up_path = os.path.dirname('.')

同样,在找到您想要的目录后,您可以与其他文件/目录路径连接

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')

从工作目录上升一级

import os
os.path.dirname(os.getcwd())

或从当前目录

import os
os.path.dirname('current path')

从当前文件路径你可以使用:

os.path.join(os.path.dirname(__file__),'..','img','banner.png')

我很惊讶处理任意数量的“;.."路径字符串中的父目录令牌不会直接由操作系统库处理。这里有一个快速而肮脏的函数,它会给你一个相对路径字符串的绝对路径字符串:

def get_abs_from_relpath(relpath:str) -> str:
ap = os.path.abspath(__file__).split("/")[:-1]
sp = relpath.split("/")
sp_start_index = 0
for slug in sp:
if slug == "..":
ap.pop(-1)
sp_start_index += 1
else:
return "/".join(ap+sp[sp_start_index:])

你可以像这样用open()调用它:

with open(get_abs_from_relpath('../../../somedir/myfile.txt')) as f:
foo = f.read()

如果你更喜欢用一行程序来获取父目录,我建议这样做:

import os
    

parent_dir = os.path.split(os.getcwd())[0]

os.path.split()方法返回一个元组(head, tail),其中tail是最后一个斜杠之后的所有内容。第一个索引是绝对路径的父节点。

不是一个回答,而是一个很长很切题的评论,可能有人会被引入歧途。

语法os.path.join( os.path.dirname( __file__ ), 'foo.txt')在运行python文件时在同一文件夹中获取文件不是"建议"对于包的解决方案,由于几个原因,包数据更受欢迎,例如在zip打包的包或更复杂的文件系统中。

pkg_resources.read_text(__package__, 'foo.txt')是以前推荐的解决方案,但在某些时候将被删除,importlib.resources.read_text(__package__, 'foo.txt')是推荐的方式-有关许多选项,请参阅https://docs.python.org/3/library/importlib.html#module-importlib.resources。 然而,这< / p >

  • 需要include_package_data=Truepackage_data,在setup.py文件中包含Dict[str, List[str]
  • 如果pip作为sdist分发(但不是内置轮子),则需要MANIFEST.in
  • 是否适用于相对导入(即未安装)
  • 在web应用程序中,由于它们的运行方式而被明智地忽略了吗