2010-01-21 15 views
75

Was wäre der beste Weg in Python festzustellen, ob ein Verzeichnis für den Benutzer schreibbar ist, der das Skript ausführt? Da dies wahrscheinlich die Verwendung des OS-Moduls beinhaltet, sollte ich erwähnen, dass ich es unter einer * nix-Umgebung betreibe.Ermitteln, ob ein Verzeichnis beschreibbar ist

Antwort

55

Es mag seltsam erscheinen, dies vorzuschlagen, sondern eine gemeinsame Python Idiom ist

Es ist einfacher für Vergebung zu bitten, als um Erlaubnis

dass Idiom Folgen, könnte man sagen:

Versuchen Sie, in das betreffende Verzeichnis zu schreiben, und fangen Sie den Fehler ab, wenn Sie nicht die entsprechende Berechtigung haben.

+4

+1 Python oder nicht, das ist wirklich der sicherste Weg für den Zugang zu testen. –

+4

Damit werden auch andere Fehler behoben, die beim Schreiben auf den Datenträger auftreten können, z. B. kein Speicherplatz mehr. Das ist die Kraft des Ausprobierens ... du musst dich nicht an alles erinnern, was schief gehen kann ;-) –

+4

Danke Leute. Entschieden, mit os.access zu gehen, da Geschwindigkeit ein wichtiger Faktor in dem ist, was ich hier mache, obwohl ich sicherlich die Verdienste in "es ist einfacher zu fragen, um Vergebung als für die Erlaubnis." ;) – illuminatedtiger

6

überprüfen Sie den Modus-Bits:

def isWritable(name): 
    uid = os.geteuid() 
    gid = os.getegid() 
    s = os.stat(dirname) 
    mode = s[stat.ST_MODE] 
    return (
    ((s[stat.ST_UID] == uid) and (mode & stat.S_IWUSR)) or 
    ((s[stat.ST_GID] == gid) and (mode & stat.S_IWGRP)) or 
    (mode & stat.S_IWOTH) 
    ) 
+2

Diese Lösung ist nur Unix. –

127

Obwohl das, was Christophe vorgeschlagen eine Pythonic Lösung ist, funktioniert das Modul o the os.access function Zugang zu überprüfen:

os.access('/path/to/folder', os.W_OK) # W_OK zum Schreiben ist, R_OK zum Lesen usw.

+4

Je nach Situation ist die "leichtere Bitte um Vergebung" nicht der beste Weg, selbst in Python. Manchmal ist es ratsam, wie bei der erwähnten os.access() - Methode "um Erlaubnis zu fragen", beispielsweise wenn die Wahrscheinlichkeit, einen Fehler zu bekommen, hoch ist. – mjv

+34

Das Testen eines Verzeichnisses für nur das Schreib-Bit reicht nicht aus, wenn Sie Dateien in das Verzeichnis schreiben möchten.Sie müssen auch auf das Execute-Bit testen, wenn Sie in das Verzeichnis schreiben wollen. os.access (‚/ path/to/Ordner‘, os.W_OK | os.X_OK) Mit os.W_OK selbst können Sie nur das Verzeichnis löschen (und nur dann, wenn das Verzeichnis leer ist) – fthinker

+3

Ein weiterer Gotcha von 'os.access() 'checkt es die * echte * UID und GID, nicht die * effektiven *. Dies könnte in SUID/SGID-Umgebungen merkwürdig sein. (‚Aber das Skript setuid root läuft, warum kann es nicht in die Datei schreiben?‘) – Alexios

9

Wenn Sie nur die Datei perms interessiert, sollte os.access(path, os.W_OK) tun, was Sie verlangen. Wenn Sie stattdessen wissen möchten, ob Sie können in das Verzeichnis schreiben, open() eine Testdatei zum Schreiben (es sollte nicht vorher existieren), fangen und untersuchen Sie alle IOError, und bereinigen Sie die Testdatei danach.

Allgemeiner, um TOCTOU Angriffe zu vermeiden (nur ein Problem, wenn Ihr Skript mit erhöhten Rechten ausgeführt wird - suid oder CGI oder so), sollten Sie diese Tests vor der Zeit nicht wirklich vertrauen, aber fallen privs, tun die open(), und erwarten Sie die IOError.

4

Hier ist etwas, das ich erstellt basierend auf ChristopheD Antwort:

import os 

def isWritable(directory): 
    try: 
     tmp_prefix = "write_tester"; 
     count = 0 
     filename = os.path.join(directory, tmp_prefix) 
     while(os.path.exists(filename)): 
      filename = "{}.{}".format(os.path.join(directory, tmp_prefix),count) 
      count = count + 1 
     f = open(filename,"w") 
     f.close() 
     os.remove(filename) 
     return True 
    except Exception as e: 
     #print "{}".format(e) 
     return False 

directory = "c:\\" 
if (isWritable(directory)): 
    print "directory is writable" 
else: 
    print "directory is not writable" 
9

über diesen Thread für Beispiele für jemanden der Suche gestolpert. Erstes Ergebnis bei Google, Glückwunsch!

Die Leute reden über die Pythonic Art, es in diesem Thread zu tun, aber keine einfachen Codebeispiele? Hier gehen Sie, für alle anderen, die in stolpert:

import sys 

filepath = 'C:\\path\\to\\your\\file.txt' 

try: 
    filehandle = open(filepath, 'w') 
except IOError: 
    sys.exit('Unable to write to file ' + filepath) 

filehandle.write("I am writing this text to the file\n") 

Diese versucht, eine Dateihandle zum Schreiben zu öffnen, und beendet mit einem Fehler, wenn die angegebene Datei kann nicht geschrieben werden: Das ist viel einfacher zu lesen, und ist eine viel bessere Art, es zu tun, anstatt Prechecks auf dem Dateipfad oder dem Verzeichnis durchzuführen, da es Race-Bedingungen vermeidet; Fälle, in denen die Datei zwischen dem Zeitpunkt, an dem die Vorprüfung ausgeführt wird, und dem tatsächlichen Versuch, in die Datei zu schreiben, nicht mehr beschreibbar ist.

+1

Dies gilt für eine Datei, nicht für ein Verzeichnis, das vom OP angefordert wurde. Sie können eine Datei in einem Verzeichnis haben und das Verzeichnis nicht beschreibbar haben, aber die Datei selbst ist, falls die Datei bereits existiert. Dies kann in der Systemadministration wichtig sein, wenn Sie zB Erstellen von Log-Dateien sind, die Sie bereits wollen existieren, aber nicht wollen Menschen ein Log-Verzeichnis für temporären Raum verwenden. –

+0

... und tatsächlich habe ich es abgelehnt, was ich jetzt für einen Fehler halte. Wie von Rohaq erwähnt, gibt es Probleme mit den Rennbedingungen. Es gibt andere Probleme auf verschiedenen Plattformen, auf denen Sie das Verzeichnis testen können, und es scheint beschreibbar zu sein, aber das ist es tatsächlich nicht. Das Ausführen plattformübergreifender Verzeichnisschreibprüfungen ist schwieriger als es aussieht. Solange Sie sich der Probleme bewusst sind, kann dies eine gute Technik sein. Ich habe es aus einer zu Unix-Perspektive betrachtet, was mein Fehler ist. Jemand bearbeitet diese Antwort, damit ich meine -1 entfernen kann. –

+0

Ich habe es bearbeitet, falls Sie die -1 :) Und ja, plattformübergreifende Verzeichnis Prüfungen können kompliziertere, entfernen möchten erhalten aber in der Regel in diesem Verzeichnis eine Datei erstellen/schreiben Sie suchen - In diesem Fall sollte das Beispiel, das ich angegeben habe, immer noch gelten. Wenn ein Problem mit der Verzeichnisberechtigung auftritt, sollte beim Versuch, das Dateihandle zu öffnen, immer noch ein IOError ausgelöst werden. – Rohaq

15

Meine Lösung des tempfile Modul:

import tempfile 
import errno 

def isWritable(path): 
    try: 
     testfile = tempfile.TemporaryFile(dir = path) 
     testfile.close() 
    except OSError as e: 
     if e.errno == errno.EACCES: # 13 
      return False 
     e.filename = path 
     raise 
    return True 
+1

Ich denke, die man mit tempfile ist der Reiniger, weil es sicher Residuen doesnt zu lassen. – grasshopper

+1

Diese Methode funktioniert nicht mit 'tempfile'. es funktioniert nur, wenn es keinen 'OSError' gibt, was bedeutet, dass es die Berechtigung hat, zu schreiben/zu löschen. Andernfalls wird 'False' nicht zurückgegeben, da kein Fehler zurückgegeben wird und das Skript nicht weiter ausgeführt oder beendet wird. nichts wird zurückgegeben. Es ist nur an dieser Linie fest. Das Erstellen einer nicht-temporären Datei wie Khattams Antwort funktioniert jedoch sowohl, wenn die Erlaubnis erlaubt oder verweigert wird. Hilfe? –

2
if os.access(path_to_folder, os.W_OK) is not True: 
      print("Folder not writable") 
else : 
      print("Folder writable") 

weitere Informationen über den Zugang kann es sein, finden here

+0

Dies ist im Grunde eine Kopie von Max Shawabkeh Antwort mit einem kleinen Wrapper um ihn herum. Macht es zu einer schnellen Kopie einfügen, aber eine bessere Idee wäre, es zu dem ursprünglichen Post von Max hinzugefügt zu haben. –

0

Wenn Sie die Erlaubnis von ein anderer Benutzer (ja müssen prüfen, I erkennen, dass dies der Frage widerspricht, aber für jemanden nützlich sein kann), können Sie es durch das Modul pwd und die Modusbits des Verzeichnisses tun.

Haftungsausschluss - funktioniert nicht unter Windows, da das POSIX-Berechtigungsmodell nicht verwendet wird (und das Modul pwd dort nicht verfügbar ist), z. - Lösung nur für * nix Systeme.

Beachten Sie, dass in einem Verzeichnis alle 3 Bits gesetzt sein müssen - Lesen, Schreiben und eXecute.
Ok, R ist kein absolutes Muss, aber ohne sie können Sie die Einträge im Verzeichnis nicht auflisten (Sie müssen also ihre Namen kennen). Execute auf der anderen Seite ist absolut notwendig - ohne dass der Benutzer die Inodes der Datei lesen kann; also auch mit W, ohne X-Dateien kann nicht erstellt oder geändert werden. More detailed explanation at this link.

Schließlich sind die Modi im stat Modul, ihre descriptions are in inode(7) man.

Beispielcode, wie zu überprüfen:

import pwd 
import stat 
import os 

def check_user_dir(user, directory): 
    dir_stat = os.stat(directory) 

    user_id, group_id = pwd.getpwnam(user).pw_uid, pwd.getpwnam(user).pw_gid 
    directory_mode = dir_stat[stat.ST_MODE] 

    # use directory_mode as mask 
    if user_id == dir_stat[stat.ST_UID] and stat.S_IRWXU & directory_mode == stat.S_IRWXU:  # owner and has RWX 
     return True 
    elif group_id == dir_stat[stat.ST_GID] and stat.S_IRWXG & directory_mode == stat.S_IRWXG: # in group & it has RWX 
     return True 
    elif stat.S_IRWXO & directory_mode == stat.S_IRWXO:          # everyone has RWX 
     return True 

    # no permissions 
    return False 
Verwandte Themen