Wie erhalte ich das übergeordnete Verzeichnis in Python?

350

Könnte mir jemand sagen, wie ich das übergeordnete Verzeichnis eines Pfads in Python plattformübergreifend abrufen kann. Z.B

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

und

C:\ ---> C:\

Wenn das Verzeichnis kein übergeordnetes Verzeichnis hat, gibt es das Verzeichnis selbst zurück. Die Frage mag einfach erscheinen, aber ich konnte sie nicht über Google ausgraben.

Mridang Agarwalla
quelle

Antworten:

481

Update von Python 3.4

Verwenden Sie das pathlibModul.

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

Alte Antwort

Versuche dies:

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

Wo yourpathist der Pfad, für den Sie das übergeordnete Element haben möchten?

Kender
quelle
136
Ihre Antwort ist richtig, aber verworren. os.path.dirnameist die Funktion dafür, wie a+=5-4ist komplizierter als a+=1. Bei der Frage wurde nur das übergeordnete Verzeichnis angefordert, nicht, ob es vorhanden ist, oder das wahre übergeordnete Verzeichnis, sofern symbolische Links im Weg stehen.
Zot
15
Es ist os.pardirnicht os.path.pardir.
Bouteillebleu
9
@outeillebleu: Beide os.pardirund os.path.pardirsind tatsächlich korrekt (sie sind identisch).
Eric O Lebigot
45
@tzot: Gibt leider os.path.dirnameunterschiedliche Ergebnisse, je nachdem, ob ein abschließender Schrägstrich im Pfad enthalten ist. Wenn Sie zuverlässige Ergebnisse erzielen möchten, müssen Sie die in der os.path.joinobigen Antwort angegebene Methode verwenden.
Artfunkel
21
Da dies anscheinend kompliziert genug ist, um eine StackOverflow-Frage zu rechtfertigen, sollte dies meiner Meinung nach als integrierte Funktion zur os.path-Bibliothek hinzugefügt werden.
antred
324

Verwenden von os.path.dirname:

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

Vorsichtsmaßnahme: os.path.dirname()Gibt unterschiedliche Ergebnisse, je nachdem, ob der Pfad einen abschließenden Schrägstrich enthält. Dies kann die gewünschte Semantik sein oder auch nicht. Vgl. @ Kenders Antwort mit os.path.join(yourpath, os.pardir).

Wai Yip Tung
quelle
6
os.path.dirname(r'C:\Program Files')Was? Python gibt Ihnen nur das Verzeichnis an, in dem sich die Datei 'Programme' befinden würde. Was mehr ist, muss es nicht einmal existieren, siehe: os.path.dirname(r'c:\i\like\to\eat\pie')Ausgänge'c:\\i\\like\\to\\eat'
Nick T
41
Das Originalplakat besagt nicht, dass das Verzeichnis vorhanden sein muss. Es gibt viele Pfadnamenmethoden, die nichts anderes als die Manipulation von Zeichenfolgen ausführen. Um zu überprüfen, ob der Pfadname tatsächlich vorhanden ist, ist ein Festplattenzugriff erforderlich. Abhängig von der Anwendung kann dies wünschenswert sein oder nicht.
Wai Yip Tung
10
Diese Lösung reagiert empfindlich auf nachfolgende os.sep. Sagen Sie os.sep == '/'. dirname (foo / bar) -> foo, aber dirname (foo / bar /) -> foo / bar
marcin
6
Das ist beabsichtigt. Es kommt auf die Interpretation eines Pfades mit einem nachgestellten / an. Betrachten Sie "Pfad1" als gleich "Pfad1 /"? Die Bibliothek verwendet die allgemeinste Interpretation, dass sie unterschiedlich sind. In einigen Zusammenhängen möchten die Leute sie möglicherweise als gleichwertig behandeln. In diesem Fall können Sie zuerst einen Streifen ('/') ausführen. Wenn die Bibliothek die andere Interpretation auswählt, verlieren Sie die Wiedergabetreue.
Wai Yip Tung
3
@ Ryan, das weiß ich nicht. Es gibt einen vollständigen RFC 1808, der geschrieben wurde, um das Problem des relativen Pfads in der URI und die Subtilität des Vorhandenseins und Fehlens eines nachgestellten / zu beheben. Wenn Sie Unterlagen kennen, die besagen, dass sie im Allgemeinen gleich behandelt werden sollten, weisen Sie darauf hin.
Wai Yip Tung
112

Die Pathlib-Methode (Python 3.4+)

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

Die traditionelle Methode

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


Welche Methode soll ich verwenden?

Verwenden Sie die traditionelle Methode, wenn:

  • Sie sind besorgt über vorhandene Fehler bei der Codegenerierung, wenn ein Pathlib-Objekt verwendet wird. (Da Pathlib-Objekte nicht mit Zeichenfolgen verknüpft werden können.)

  • Ihre Python-Version ist kleiner als 3.4.

  • Sie benötigen eine Zeichenfolge und haben eine Zeichenfolge erhalten. Angenommen, Sie haben eine Zeichenfolge, die einen Dateipfad darstellt, und Sie möchten das übergeordnete Verzeichnis abrufen, damit Sie es in eine JSON-Zeichenfolge einfügen können. Es wäre irgendwie albern, dafür in ein Pathlib-Objekt und wieder zurück zu konvertieren.

Wenn keine der oben genannten Bedingungen zutrifft, verwenden Sie Pathlib.



Was ist Pathlib?

Wenn Sie nicht wissen, was Pathlib ist, ist das Pathlib-Modul ein großartiges Modul, das Ihnen das Arbeiten mit Dateien noch einfacher macht. Die meisten, wenn nicht alle integrierten Python-Module, die mit Dateien arbeiten, akzeptieren sowohl Pathlib-Objekte als auch Zeichenfolgen. Ich habe nachfolgend einige Beispiele aus der Pathlib-Dokumentation hervorgehoben , die einige der netten Dinge zeigen, die Sie mit Pathlib tun können.

Navigieren in einem Verzeichnisbaum:

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

Pfadeigenschaften abfragen:

>>> q.exists()
True
>>> q.is_dir()
False
wp-overwatch.com
quelle
4
Dies ist die einzig vernünftige Antwort. Wenn Sie gezwungen sind, Python 2 zu verwenden, verwenden Sie einfach pip install pathlib2den Backport.
Navin
1
Diese Lösung ist NICHT empfindlich gegen Schleppen os.sep!
Dylan F
35
import os
p = os.path.abspath('..')

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

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

ivo
quelle
7
Dies erhält nur das übergeordnete Element des CWD, nicht das übergeordnete Element eines beliebigen Pfads, wie vom OP angefordert.
Sergio
Fügen Sie die doppelten Punkte am Ende Ihrer URL hinzu und es wird funktionieren. ZB os.path.abspath(r'E:\O3M_Tests_Embedded\branches\sw_test_level_gp\test_scripts\..\..') Ergebnis:E:\\O3M_Tests_Embedded\\branches
Arindam Roychowdhury
Dies bedeutet : /.
Loretoparisi
26

Eine alternative Lösung von @kender

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

Wo yourpathist der Pfad, für den Sie das übergeordnete Element haben möchten?

Diese Lösung ist jedoch nicht perfekt, da sie nicht den Fall behandelt, in dem es sich yourpathum eine leere Zeichenfolge oder einen Punkt handelt.

Diese andere Lösung wird diesen Eckfall besser handhaben:

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

Hier die Ausgänge für jeden Fall, der gefunden werden kann (Eingabepfad ist relativ):

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))    => '../..'

Der Eingabepfad ist absolut (Linux-Pfad):

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))     => '/'
benjarobin
quelle
Das Normalisieren des Pfads ist immer eine gute Vorgehensweise, insbesondere bei plattformübergreifenden Arbeiten.
DevPlayer
Das ist die richtige Antwort! Es hält relative Pfade relativ. Vielen Dank!
Maxim
@ Maxim Diese Lösung war nicht perfekt, ich habe sie verbessert, da die ursprüngliche Lösung nicht einen Fall behandelt
Benjaminobin
@benjarobin Ja, ich hatte nicht an den Eckfall gedacht. Vielen Dank.
Maxim
18
os.path.split(os.path.abspath(mydir))[0]
Dan Menes
quelle
Dies funktioniert nicht für Pfade, die zu einem Verzeichnis führen, sondern gibt das Verzeichnis einfach erneut zurück.
Anthony Briggs
2
@AnthonyBriggs, ich habe es gerade mit Python 2.7.3 unter Ubuntu 12.04 versucht und es scheint gut zu funktionieren. os.path.split(os.path.abspath("this/is/a/dir/"))[0]kehrt '/home/daniel/this/is/a'wie erwartet zurück. Ich habe im Moment kein laufendes Windows-Kästchen, um es dort zu überprüfen. Bei welchem ​​Setup haben Sie das von Ihnen gemeldete Verhalten beobachtet?
Dan Menes
Du könntest es tun parentdir = os.path.split(os.path.apspath(dir[:-1]))[0]. Ich bin mir sicher, dass dies funktioniert, denn wenn am Ende ein Schrägstrich vorhanden ist, wird dieser entfernt. Wenn kein Schrägstrich vorhanden ist, funktioniert dies aufgrund des vorhergehenden Schrägstrichs weiterhin (auch wenn der letzte Teil des Pfads nur ein Zeichen lang ist). Dies setzt natürlich voraus, dass der Pfad korrekt ist und nicht so etwas wie sagt /a//b/c///d////(unter Unix ist dies immer noch gültig), was in den meisten Fällen (richtig) ist, insbesondere wenn Sie so etwas os.path.abspathoder eine andere os.pathFunktion ausführen.
dylnmc
Um vielen Schrägstrichen am Ende entgegenzuwirken, können Sie auch eine kleine for-Schleife schreiben, die diese entfernt. Ich bin mir sicher, dass es sogar einen cleveren Einzeiler geben könnte, oder vielleicht das und os.path.split in einer Zeile.
dylnmc
@Den Menes Ich habe gerade gesehen, wie du einen Kommentar abgegeben hast. Es funktioniert nicht, wenn Sie so etwas wie os.path.split("a/b//c/d///")und zum Beispiel cd //////dev////// is equivalent to cd / dev / `oder haben cd /dev; Alle diese sind unter Linux gültig. Ich habe mir das gerade ausgedacht und es kann jedoch nützlich sein : os.path.split(path[:tuple(ind for ind, char in enumerate(path) if char != "/" and char != "\\")[-1]])[0]. (Dies sucht im Wesentlichen nach dem letzten Nicht-Schrägstrich und ruft die Teilzeichenfolge des Pfads bis zu diesem Zeichen ab.) Ich habe path = "/a//b///c///d////"die oben genannte Anweisung verwendet und dann ausgeführt und erhalten '/a//b///c'.
dylnmc
14
os.path.abspath(os.path.join(somepath, '..'))

Beobachten:

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', '..'))
Ignacio Vazquez-Abrams
quelle
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 "------------------------------------------------------------"
Großvater
quelle
6

Wenn Sie nur den Namen des Ordners möchten , der das unmittelbare übergeordnete Element der als Argument angegebenen Datei ist, und nicht den absoluten Pfad zu dieser Datei:

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

dh mit einem currentDirWert von/home/user/path/to/myfile/file.ext

Der obige Befehl gibt Folgendes zurück:

myfile

8bitjunkie
quelle
3
os.path.basename (os.path.dirname (current_dir)) funktioniert auch hier.
DevPlayer
4
>>> import os
>>> os.path.basename(os.path.dirname(<your_path>))

Zum Beispiel in Ubuntu:

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

Zum Beispiel in Windows:

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

Beide Beispiele wurden in Python 2.7 ausprobiert

Soumendra
quelle
3
import os.path

os.path.abspath(os.pardir)
Washington Botelho
quelle
Dies setzt voraus, dass Sie das übergeordnete Verzeichnis des "aktuellen Arbeitsverzeichnisses" und das übergeordnete Verzeichnis im Allgemeinen keinen Pfad haben möchten.
DevPlayer
3

Angenommen, wir haben eine Verzeichnisstruktur wie

1]

/home/User/P/Q/R

Wir wollen aus dem Verzeichnis R auf den Pfad von "P" zugreifen, dann können wir mit verwenden

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

2]

/home/User/P/Q/R

Wir möchten vom Verzeichnis R aus auf den Pfad des Verzeichnisses "Q" zugreifen, dann können wir mit verwenden

ROOT = os.path.abspath(os.path.join(".", os.pardir));
Rakesh Chaudhari
quelle
2

Fügen Sie einfach etwas zur Antwort des Tung hinzu (Sie müssen verwenden rstrip('/'), um sicherer zu sein, wenn Sie sich auf einer Unix-Box befinden).

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

Aber wenn Sie nicht verwenden rstrip('/'), ist Ihre Eingabe gegeben

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

würde ausgeben,

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

Das ist wahrscheinlich nicht das, was Sie sehen, da Sie beides wollen "../data/replies/" und "../data/replies"sich gleich verhalten.

Samsamara
quelle
1
Ich würde empfehlen, "Eingabe" nicht als Variable / Referenz zu verwenden. Es ist eine eingebaute Funktion.
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))
Miguel Mota
quelle
1
print os.path.abspath(os.path.join(os.getcwd(), os.path.pardir))

Sie können dies verwenden, um das übergeordnete Verzeichnis des aktuellen Speicherorts Ihrer py-Datei abzurufen.

Eros Nikolli
quelle
2
Dieser Vorschlag führt oft zu Fehlern. os.getcwd () ist oft NICHT dort, wo "Ihre py-Datei" ist. Denken Sie an Pakete. Wenn ich "some_package_with_subpackages" importiere, befinden sich viele Module nicht im obersten Verzeichnis dieses Pakets. os.getcwd () gibt zurück, wo Sie das oberste Skript ausführen. Und das setzt auch voraus, dass Sie dies über eine Befehlszeile tun.
DevPlayer
0

Holen Sie sich den Pfad des übergeordneten Verzeichnisses und erstellen Sie ein neues Verzeichnis (Name new_dir).

Pfad des übergeordneten Verzeichnisses abrufen

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

Beispiel 1

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

Beispiel 2

import os
print os.makedirs(os.path.join(os.path.dirname(__file__), os.path.abspath('..'), 'new_dir'))
Jay Patel
quelle
0
os.path.abspath('D:\Dir1\Dir2\..')

>>> 'D:\Dir1'

Also ..hilft ein

Arindam Roychowdhury
quelle
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))
fuyunliu
quelle
0

Die oben gegebenen Antworten sind alle vollkommen in Ordnung, um eine oder zwei Verzeichnisebenen zu erreichen, aber sie können etwas umständlich werden, wenn man den Verzeichnisbaum um viele Ebenen (z. B. 5 oder 10) durchlaufen muss. Dies kann präzise erfolgen, indem eine Liste von N os.pardirs in hinzugefügt wird os.path.join. Beispiel:

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))
MPA
quelle