Python'da üst dizini nasıl edinebilirim?


350

Birisi bana Python'da bir yolun üst dizinini çapraz platformda nasıl alacağımı söyleyebilir. Örneğin

C:\Program Files ---> C:\

ve

C:\ ---> C:\

Dizinin bir üst dizini yoksa dizinin kendisini döndürür. Soru basit görünebilir, ancak Google üzerinden bulamadım.

Yanıtlar:


481

Python 3.4'ten güncelleme

pathlibModülü kullanın .

from pathlib import Path
path = Path("/here/your/path/file.txt")
print(path.parent)

Eski cevap

Bunu dene:

import os.path
print os.path.abspath(os.path.join(yourpath, os.pardir))

yourpathebeveynin olmasını istediğiniz yol nerede .


137
Cevabınız doğru ama kıvrık; os.path.dirnameBunun işlevi a+=5-4, daha kıvrımlı gibi a+=1. Soru, var olup olmadığı değil, yalnızca üst dizinin ya da sembolik bağların önüne geçtiği gerçek üst dizinin sorulmasını istedi .
tzot

16
Öyle os.pardirdeğil os.path.pardir.
bouteillebleu

9
@bouteillebleu: Her ikisi de os.pardirve os.path.pardiraslında doğrudur (özdeştir).
Eric O Lebigot

45
@tzot: maalesef yola os.path.dirnamebir eğik çizgi eklenip eklenmediğine bağlı olarak farklı sonuçlar verir. Güvenilir sonuçlar istiyorsanız, os.path.joinyukarıdaki cevaptaki yöntemi kullanmanız gerekir .
Artfunkel

21
Bu, bir StackOverflow sorusunu garanti edecek kadar karmaşık olduğu için, bunun os.path kütüphanesine yerleşik bir işlev olarak eklenmesi gerektiğini hissediyorum.
antred

324

Kullanma os.path.dirname:

>>> os.path.dirname(r'C:\Program Files')
'C:\\'
>>> os.path.dirname('C:\\')
'C:\\'
>>>

Uyarı: os.path.dirname()yola bir eğik çizgi eklenip eklenmediğine bağlı olarak farklı sonuçlar verir. Bu istediğiniz anlambilim olabilir veya olmayabilir. Krş @ kender'in cevabını kullanarak os.path.join(yourpath, os.pardir).


6
os.path.dirname(r'C:\Program Files')ne? Python size sadece 'Program Files' dosyasının bulunduğu dizini veriyor. Dahası, var olmak zorunda bile değil, işte: os.path.dirname(r'c:\i\like\to\eat\pie')çıktılar'c:\\i\\like\\to\\eat'
Nick T

41
Orijinal poster dizinin var olması gerektiğini belirtmez. Dize manipülasyonundan başka bir şey yapmayan birçok yol adı yöntemi vardır. Yol adının gerçekten var olup olmadığını doğrulamak için bir disk erişimi gerekir. Uygulamaya bağlı olarak bu istenebilir veya edilmeyebilir.
Wai Yip Tung

10
bu çözüm sondaki os.sep'e duyarlıdır. Os.sep == '/' deyin. dirname (foo / bar) -> foo, ancak dirname (foo / bar /) -> foo / bar
marcin

6
Bu tasarım gereğidir. Bir yolun izini süren yorumu ile ilgilidir. "Path1" in "path1 /" e eşit olduğunu düşünüyor musunuz? Kütüphane, farklı oldukları en genel yorumu kullanır. Bazı bağlamlarda insanlar onlara eşdeğer muamele etmek isteyebilir. Bu durumda önce bir rstrip ('/') yapabilirsiniz. Kütüphane diğer yorumu seçtiyse, sadakatini kaybedersiniz.
Wai Yip Tung

3
@Ryan, bunu bilmiyorum. URI'deki göreceli yol konusunu ve bir iz / Genel olarak eşdeğer muamele görmesi gerektiğini söyleyen herhangi bir belge biliyorsanız lütfen belirtiniz.
Wai Yip Tung

112

Pathlib yöntemi (Python 3.4+)

from pathlib import Path
Path('C:\Program Files').parent
# Returns a Pathlib object

Geleneksel yöntem

import os.path
os.path.dirname('C:\Program Files')
# Returns a string


Hangi yöntemi kullanmalıyım?

Aşağıdaki durumlarda geleneksel yöntemi kullanın:

  • Bir Pathlib nesnesi kullanılacaksa, varolan kod üreten hatalardan endişe ediyorsunuz. (Pathlib nesneleri dizelerle birleştirilemediğinden.)

  • Python sürümünüz 3.4'ten küçük.

  • Bir dizeye ihtiyacınız var ve bir dize aldınız. Diyelim ki bir dosya yolunu temsil eden bir dizeniz var ve bunu JSON dizesine koyabilmeniz için üst dizini almak istiyorsunuz. Bir Pathlib nesnesine dönüştürmek ve bunun için tekrar geri dönmek saçma olurdu.

Yukarıdakilerin hiçbiri geçerli değilse Pathlib kullanın.



Pathlib nedir?

Pathlib'in ne olduğunu bilmiyorsanız, Pathlib modülü, dosyalarla çalışmayı sizin için daha da kolaylaştıran müthiş bir modüldür. Dosyalarla çalışan yerleşik Python modüllerinin tümü olmasa da çoğu Pathlib nesnelerini ve dizelerini kabul eder. Pathlib ile yapabileceğiniz bazı düzgün şeyleri gösteren Pathlib belgelerinden birkaç örneği aşağıda vurguladım.

Bir dizin ağacında gezinme:

>>> p = Path('/etc')
>>> q = p / 'init.d' / 'reboot'
>>> q
PosixPath('/etc/init.d/reboot')
>>> q.resolve()
PosixPath('/etc/rc.d/init.d/halt')

Sorgu yolu özellikleri:

>>> q.exists()
True
>>> q.is_dir()
False

4
Tek aklı başında cevap bu. Python 2'yi kullanmak zorunda kalırsanız, sadece pip install pathlib2backport'u kullanın.
Navin

1
Bu çözüm, izlemeye duyarlı DEĞİLDİR os.sep!
Dylan F

35
import os
p = os.path.abspath('..')

C:\Program Files ---> C:\\\

C:\ ---> C:\\\


7
Bu, OP'nin istediği gibi keyfi bir yolun üst öğesini değil, yalnızca CWD'nin üst öğesini alır.
Sergio

URL'nizin sonuna çift noktaları ekleyin ve işe yarayacaktır. os.path.abspath(r'E:\O3M_Tests_Embedded\branches\sw_test_level_gp\test_scripts\..\..') Sonuç:E:\\O3M_Tests_Embedded\\branches
Arindam Roychowdhury

Bunun anlamı şudur: /.
loretoparisi

26

@Kender'ın alternatif bir çözümü

import os
os.path.dirname(os.path.normpath(yourpath))

yourpathebeveynin olmasını istediğiniz yol nerede .

Ancak bu çözüm mükemmel değildir, çünkü yourpathboş bir dize veya bir nokta olduğu durumu ele almayacaktır .

Bu diğer çözüm, bu köşe davasını daha iyi idare edecek:

import os
os.path.normpath(os.path.join(yourpath, os.pardir))

Burada bulabileceğiniz her durum için çıkışlar (Giriş yolu göreceli):

os.path.dirname(os.path.normpath('a/b/'))          => 'a'
os.path.normpath(os.path.join('a/b/', os.pardir))  => 'a'

os.path.dirname(os.path.normpath('a/b'))           => 'a'
os.path.normpath(os.path.join('a/b', os.pardir))   => 'a'

os.path.dirname(os.path.normpath('a/'))            => ''
os.path.normpath(os.path.join('a/', os.pardir))    => '.'

os.path.dirname(os.path.normpath('a'))             => ''
os.path.normpath(os.path.join('a', os.pardir))     => '.'

os.path.dirname(os.path.normpath('.'))             => ''
os.path.normpath(os.path.join('.', os.pardir))     => '..'

os.path.dirname(os.path.normpath(''))              => ''
os.path.normpath(os.path.join('', os.pardir))      => '..'

os.path.dirname(os.path.normpath('..'))            => ''
os.path.normpath(os.path.join('..', os.pardir))    => '../..'

Giriş yolu mutlaktır (Linux yolu):

os.path.dirname(os.path.normpath('/a/b'))          => '/a'
os.path.normpath(os.path.join('/a/b', os.pardir))  => '/a'

os.path.dirname(os.path.normpath('/a'))            => '/'
os.path.normpath(os.path.join('/a', os.pardir))    => '/'

os.path.dirname(os.path.normpath('/'))             => '/'
os.path.normpath(os.path.join('/', os.pardir))     => '/'

Yolun normalleştirilmesi, özellikle çapraz platform çalışması yaparken her zaman iyi bir uygulamadır.
DevPlayer

Bu doğru cevap! Göreli yolları göreceli tutar. Teşekkürler!
Maxim

@Maxim Bu çözüm mükemmel değildi, orijinal çözüm bir vakayı ele almadığı için geliştirdim
benjarobin

@benjarobin Evet, köşe davasını düşünmemiştim. Teşekkürler.
Maxim

18
os.path.split(os.path.abspath(mydir))[0]

Bu bir dizine giden yollar için işe yaramaz, sadece dizini tekrar döndürür.
Anthony Briggs

2
@AnthonyBriggs, ben sadece Ubuntu 12.04 Python 2.7.3 kullanarak denedim ve iyi çalışıyor gibi görünüyor. beklendiği gibi os.path.split(os.path.abspath("this/is/a/dir/"))[0]döner '/home/daniel/this/is/a'. Şu anda kontrol etmek için çalışan bir Windows kutum yok. Hangi kurulumda bildirdiğiniz davranışı gözlemlediniz?
Dan Menes

Yapabilirsin parentdir = os.path.split(os.path.apspath(dir[:-1]))[0]. Bu - eminim - işe yarıyor çünkü sonunda bir eğik çizgi varsa, o zaman kaldırılır; eğik çizgi yoksa, önceki eğik çizgi nedeniyle bu yine de çalışır (yolun son kısmı yalnızca bir karakter uzunluğunda olsa bile). Bu elbette yolun uygun olduğunu varsayar ve böyle bir şey söylemez /a//b/c///d////(unix'te bu hala geçerlidir), çoğu durumda özellikle uygun bir şey os.path.abspathveya başka bir os.pathişlev yaptığınızda (uygun) olurlar .
dylnmc

Ayrıca, sonunda çok fazla eğik çizgiye karşı koymak için, bunları kaldıran bir döngü için küçük bir yazı yazabilirsiniz. Eminim, bunu yapmak için akıllı bir tek astar bile olabilir, ya da belki bunu yapın ve bir satırda os.path.split.
dylnmc

@ Men Menes Az önce seni yorum gördüm. Böyle bir şey varsa işe yaramaz os.path.split("a/b//c/d///")ve örneğin cd //////dev////// is equivalent to cd / dev / `veya cd /dev; bunların hepsi linux için geçerlidir. Sadece bu geldi ve onu da, yararlı olabilir: os.path.split(path[:tuple(ind for ind, char in enumerate(path) if char != "/" and char != "\\")[-1]])[0]. (Bu aslında son eğik olmayan arar, ve bu char kadar yolun alt dize alır.) Ben kullandım path = "/a//b///c///d////"ve sonra yukarıda belirtilen deyimi koştu ve var '/a//b///c'.
dylnmc

14
os.path.abspath(os.path.join(somepath, '..'))

Gözlemek:

import posixpath
import ntpath

print ntpath.abspath(ntpath.join('C:\\', '..'))
print ntpath.abspath(ntpath.join('C:\\foo', '..'))
print posixpath.abspath(posixpath.join('/', '..'))
print posixpath.abspath(posixpath.join('/home', '..'))

7
import os
print"------------------------------------------------------------"
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
print("example 1: "+SITE_ROOT)
PARENT_ROOT=os.path.abspath(os.path.join(SITE_ROOT, os.pardir))
print("example 2: "+PARENT_ROOT)
GRANDPAPA_ROOT=os.path.abspath(os.path.join(PARENT_ROOT, os.pardir))
print("example 3: "+GRANDPAPA_ROOT)
print "------------------------------------------------------------"

6

İsterseniz sadece isim bir argüman ve olarak verilmiştir dosyanın derhal üstüdür klasörün değil mutlak yolu o dosyaya:

os.path.split(os.path.dirname(currentDir))[1]

yani currentDirdeğeri/home/user/path/to/myfile/file.ext

Yukarıdaki komut geri dönecektir:

myfile


3
os.path.basename (os.path.dirname (current_dir)) burada da çalışır.
DevPlayer

4
>>> import os
>>> os.path.basename(os.path.dirname(<your_path>))

Örneğin Ubuntu'da:

>>> my_path = '/home/user/documents'
>>> os.path.basename(os.path.dirname(my_path))
# Output: 'user'

Örneğin Windows'ta:

>>> my_path = 'C:\WINDOWS\system32'
>>> os.path.basename(os.path.dirname(my_path))
# Output: 'WINDOWS'

Her iki örnek de Python 2.7'de denendi



3

Diyelim ki dizin yapımız var

1]

/home/User/P/Q/R

"P" nin yoluna R dizininden erişmek istiyoruz ve o zaman

ROOT = os.path.abspath(os.path.join("..", os.pardir));

2]

/home/User/P/Q/R

"Q" dizininin yoluna R dizininden erişmek istiyoruz ve o zaman

ROOT = os.path.abspath(os.path.join(".", os.pardir));

2

Sadece Tung'un cevabına bir şey ekleyerek ( rstrip('/')unix kutusundaysanız daha güvenli taraf olmak için kullanmanız gerekir ).

>>> input = "../data/replies/"
>>> os.path.dirname(input.rstrip('/'))
'../data'
>>> input = "../data/replies"
>>> os.path.dirname(input.rstrip('/'))
'../data'

Ancak, kullanmazsanız rstrip('/'), girdiniz

>>> input = "../data/replies/"

çıktı,

>>> os.path.dirname(input)
'../data/replies'

hangi sen hem istediğiniz gibi bakıyoruz muhtemelen ne olduğunu "../data/replies/"ve "../data/replies"aynı şekilde davranmaya.


1
Değişken / referans olarak "giriş" kullanılmamasını tavsiye ederim. Yerleşik bir işlevdir.
DevPlayer

2
import os

dir_path = os.path.dirname(os.path.realpath(__file__))
parent_path = os.path.abspath(os.path.join(dir_path, os.pardir))

1
print os.path.abspath(os.path.join(os.getcwd(), os.path.pardir))

Bunu, py dosyanızın geçerli konumunun üst dizinini almak için kullanabilirsiniz.


2
Bu öneri genellikle hatalara yol açar. os.getcwd () genellikle "py dosyanızın" olduğu DEĞİLDİR. Paketleri düşünün. "Some_package_with_subpackages" ı içe aktarırsam, birçok modül bu paketin en üst dizininde yer almaz. os.getcwd (), en üstteki komut dosyasını yürüttüğünüz yere döner. Ve bu da komut satırından yaptığınızı varsayar.
DevPlayer

0

Üst Dizin Yolu ALIN ve Yeni dizin (ad new_dir) yapın

Üst Dizin Yolunu Al

os.path.abspath('..')
os.pardir

örnek 1

import os
print os.makedirs(os.path.join(os.path.dirname(__file__), os.pardir, 'new_dir'))

ÖRNEK 2

import os
print os.makedirs(os.path.join(os.path.dirname(__file__), os.path.abspath('..'), 'new_dir'))


0
import os

def parent_filedir(n):
    return parent_filedir_iter(n, os.path.dirname(__file__))

def parent_filedir_iter(n, path):
    n = int(n)
    if n <= 1:
        return path
    return parent_filedir_iter(n - 1, os.path.dirname(path))

test_dir = os.path.abspath(parent_filedir(2))

0

Yukarıda verilen cevapların tümü, bir veya iki dizin seviyesine çıkmak için mükemmeldir, ancak dizin ağacını birçok düzeyden geçmesi gerekiyorsa biraz hantal olabilir (örneğin, 5 veya 10). Bu bir listesini katılarak kısaca yapılabilir N os.pardiriçinde s os.path.join. Misal:

import os
# Create list of ".." times 5
upup = [os.pardir]*5
# Extract list as arguments of join()
go_upup = os.path.join(*upup)
# Get abspath for current file
up_dir = os.path.abspath(os.path.join(__file__, go_upup))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.