Sử dụng os.path của Python, làm cách nào để lên một thư mục?


224

Gần đây tôi đã nâng cấp Django từ v1.3.1 lên v1.4.

settings.pyTôi già

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

Điều này sẽ trỏ đến /Users/hobbes3/Sites/mysite/templates, nhưng vì Django v1.4 đã chuyển thư mục dự án về cùng cấp với các thư mục ứng dụng , nên settings.pytệp của tôi hiện đang ở /Users/hobbes3/Sites/mysite/mysite/thay vì /Users/hobbes3/Sites/mysite/.

Vì vậy, thực sự câu hỏi của tôi bây giờ có hai mặt:

  1. Làm thế nào để tôi sử dụng os.pathđể xem một thư mục một cấp trên __file__. Nói cách khác, tôi muốn /Users/hobbes3/Sites/mysite/mysite/settings.pytìm /Users/hobbes3/Sites/mysite/templatesbằng cách sử dụng các đường dẫn tương đối.
  2. Tôi có nên giữ templatethư mục (trong đó có các mẫu cross-ứng dụng, như admin, registration, vv) tại dự án /User/hobbes3/Sites/mysitecấp hoặc tại /User/hobbes3/Sites/mysite/mysite?

Cant bạn chỉ cần sử dụng osđến cdđể ../mysite? Hoặc bất cứ lệnh nào bạn muốn
prelic

@prelic Hmm? Tôi không hiểu Tôi đang cố gắng tránh mã hóa đường dẫn, bởi vì tôi sử dụng giống nhau settings.pytrong nhiều máy chủ. Sự khác biệt duy nhất có thể là thông tin cơ sở dữ liệu. Tôi đã đọc os.pathtài liệu nhưng tôi không thể tìm thấy một lệnh cho phép bạn đi lên một thư mục. Thích cd ...
hobbes3

2
@ hobbes3 Bạn chỉ có thể có os.path.join( os.path.dirname( __file__ ), '..' ) ..nghĩa là thư mục ở trên trong toàn bộ hệ thống tập tin, không chỉ khi được chuyển đến cd.
Michael Berkowski

3
@Michael, có lẽ tốt hơn để sử dụngos.path.join( os.path.dirname ( __file__), os.path.pardir)
mgilson

Câu trả lời:


285
os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))

Theo như thư mục mẫu sẽ đi đâu, tôi không biết vì Django 1.4 vừa mới ra mắt và tôi chưa nhìn vào nó. Có lẽ bạn nên hỏi một câu hỏi khác về SE để giải quyết vấn đề đó.

Bạn cũng có thể sử dụng normpathđể dọn sạch đường dẫn, hơn là abspath. Tuy nhiên, trong tình huống này, Django mong đợi một con đường tuyệt đối chứ không phải là một con đường tương đối.

Đối với khả năng tương thích đa nền tảng, sử dụng os.pardirthay vì '..'.


4
Đó là một ý tưởng tồi để sử dụng ..hoặc một cái gì đó? Tại sao câu trả lời này nhận được ít phiếu hơn?
hobbes3

1
Tôi không biết tại sao nó lại nhận được ít phiếu hơn, nhưng đó là thứ tôi luôn sử dụng. Nó thậm chí được định nghĩa trong ví dụ cho normpath. Thêm vào đó, nó sẽ đi qua các liên kết tượng trưng đúng cách.
tạm biệt

1
Sử dụng abspath sẽ chỉ làm sạch nó một chút. Nếu nó không có ở đó, chuỗi thực tế cho tên đường dẫn sẽ /Users/hobbes3/Sites/mysite/mysite/../templateshoàn toàn ổn, nhưng chỉ lộn xộn hơn một chút. Nó cũng đảm bảo rằng lời nhắc của Django về việc sử dụng các đường dẫn tuyệt đối được tuân theo. Nếu bạn đang ở trong một tình huống khác sử dụng một đường dẫn tương đối, bạn nên sử dụng Normpath để đơn giản hóa các đường dẫn của mình.
tạm biệt

2
Câu hỏi này chỉ được hỏi về cấu trúc thư mục di chuyển cho phiên bản mới của Django , vì vậy có lẽ bạn nên xem xét vấn đề đó để giải quyết vấn đề thứ hai của mình.
tạm biệt

1
@Zitrax Bạn có biết bất kỳ nền tảng nào có sự khác biệt này không, hay nó chỉ ở đó để đảm bảo an toàn trong tương lai? (Tôi thực sự không biết về điều đó os.pardir, chưa bao giờ thực sự đi đến tận cùng của ostài liệu)
trước đến

98

Để lấy thư mục của một tập tin, chỉ cần sử dụng:

os.path.dirname(path) 

Để có được một thư mục, chỉ cần sử dụng os.path.dirnamelại

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

Bạn có thể muốn kiểm tra nếu __file__là một liên kết tượng trưng:

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

17
Có cách nào để đi lên ncác thư mục mà không phải gọi os.path.dirname nthời gian?
Oriol Nieto

9
@OriolNieto Có, kể từ phiên bản Python 3.4+ bạn có thể sử dụng pathlib.Path.parents[levels_up-1]. Xem câu hỏi này để biết thêm giải pháp
jwalton

23

Nếu bạn đang sử dụng Python 3.4 hoặc mới hơn, một cách thuận tiện để di chuyển lên nhiều thư mục là 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])  # "."

2
Đây chắc chắn là phương pháp sạch nhất.
hobbes3

18

Bạn muốn chính xác điều này:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )

9

Cá nhân, tôi muốn tiếp cận chức năng

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

current_dirs_parent = get_parent_dir(os.getcwd())

Hãy cẩn thận câu trả lời này không hoạt động nếu đầu vào có dấu gạch chéo, ví dụ os.path.dirname('/tmp/lala/')vẫn trả về'/tmp/lala'
Fruit

Trường hợp dấu gạch chéo có thể tham khảo câu trả lời này: stackoverflow.com/a/25669963/1074998
Fruit

7

Tôi nghĩ rằng cách dễ nhất để làm là chỉ sử dụng lại dirname () Vì vậy, bạn có thể gọi

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

nếu bạn gửi tại /Users/hobbes3/Sites/mysite/temsheet/method.py

Điều này sẽ trả về "/ Người dùng / hobbes3 / Trang web / mysite"


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

Cập nhật:

Nếu bạn settings.pytình cờ "sao chép" thông qua liên kết tượng trưng, ​​câu trả lời của @ forivall sẽ tốt hơn:

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

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

Phương thức trên sẽ 'thấy' wrong.htmltrong khi phương thức của @ forivall sẽ thấyright.html

Trong sự vắng mặt của các liên kết tượng trưng, ​​hai câu trả lời giống hệt nhau.


Có điều gì sai với cách tiếp cận này? Nó hoạt động tốt và nhìn đẹp nhưng một chút hackish;)
Gricha

Nó hơi khác với câu trả lời được chấp nhận trong cách nó xử lý các liên kết. Họ giống hệt nhau.
Antony Hatchkins

6

Điều này có thể hữu ích cho các trường hợp khác mà bạn muốn tăng x thư mục. Chỉ cần chạy walk_up_folder(path, 6)để đi lên 6 thư mục.

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

Chỉ có thể sử dụng for _ in xrange(depth)thay vì theo dõi các biến cục bộ.
Zitrax

2

Đối với một người hoang tưởng như tôi, tôi thích cái này

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

8
có lẽ thay vì '/'bạn nên sử dụngos.sep
djhaskin987

1

Để đi nthư mục lên ... chạyup(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


0

Với việc sử dụng os.pathchúng ta có thể đi lên một thư mục như thế

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

Ngoài ra, sau khi tìm thấy thư mục bạn muốn, bạn có thể tham gia với đường dẫn tệp / thư mục khác

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.