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
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.
ü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)
)
Diese Lösung ist nur Unix. –
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.
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
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
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
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
.
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"
ü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.
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. –
... 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. –
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
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
Ich denke, die man mit tempfile ist der Reiniger, weil es sicher Residuen doesnt zu lassen. – grasshopper
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? –
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
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. –
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
+1 Python oder nicht, das ist wirklich der sicherste Weg für den Zugang zu testen. –
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 ;-) –
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