web-dev-qa-db-de.com

Bestimmen, ob ein Verzeichnis schreibbar ist

Wie kann man in Python am besten feststellen, ob ein Verzeichnis für den Benutzer, der das Skript ausführt, schreibbar ist? Da dies wahrscheinlich die Verwendung des os-Moduls erfordert, sollte ich erwähnen, dass ich es in einer * nix-Umgebung betreibe. 

85

Obwohl das, was Christophe vorschlug, eine mehr Pythonic-Lösung ist, verfügt das os-Modul über die os.access-Funktion , um den Zugriff zu prüfen:

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

144
Max Shawabkeh

Es mag seltsam erscheinen, dies vorzuschlagen, aber eine gängige Python-Redewendung ist 

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

Nach dieser Redewendung könnte man sagen:

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

61
ChristopheD

Meine Lösung mit dem Modul tempfile:

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
15
zak

Stolperte über diesen Thread und suchte nach Beispielen für jemanden. Erstes Ergebnis bei Google, Glückwunsch!

Die Leute sprechen in diesem Thread über die Pythonic-Methode, aber keine einfachen Codebeispiele? Hier geht's für alle anderen, die stolpern:

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

Dadurch wird versucht, ein Dateihandle zum Schreiben zu öffnen. Wenn die angegebene Datei nicht geschrieben werden kann, wird ein Fehler angezeigt. Dies ist viel einfacher zu lesen und bietet eine viel bessere Möglichkeit, dies zu tun, als Vorprüfungen für den Dateipfad oder das Verzeichnis , da es Rennbedingungen vermeidet; Fälle, in denen die Datei zwischen dem Zeitpunkt, zu dem Sie die Vorabprüfung ausführen, und dem tatsächlichen Versuch, in die Datei zu schreiben, nicht beschrieben werden können. 

10
Rohaq

Wenn Sie sich nur für die Dateibewegungen interessieren, sollte os.access(path, os.W_OK) das tun, wonach Sie fragen. Wenn Sie stattdessen wissen möchten, ob Sie can in das Verzeichnis schreiben, open() eine Testdatei zum Schreiben (diese sollte vorher nicht vorhanden sein), fangen und prüfen Sie alle IOError-Dateien und bereinigen Sie anschließend die Testdatei.

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 im Allgemeinen diesen Voraus-Tests nicht wirklich vertrauen, sondern Privs ablegen , machen Sie die open() und erwarten Sie die IOError.

9
sverkerw

Überprüfen Sie die Modusbits: 

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)
     )
7
Joe Koberg

Hier ist etwas, das ich basierend auf ChristopheDs Antwort erstellt habe:

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"
4
khattam
 if os.access(path_to_folder, os.W_OK) is not True:
            print("Folder not writable")
 else :
            print("Folder writable")

weitere Informationen zum Zugang finden Sie hier hier

2
Softmixt

Ich bin auf dieses Bedürfnis gestoßen, als ich über argparse ein Argument hinzugefügt habe. Das eingebaute type=FileType('w') würde für mich nicht funktionieren, da ich nach einem Verzeichnis suchte. Am Ende schrieb ich meine eigene Methode, um mein Problem zu lösen. Hier ist das Ergebnis mit argparse snippet.

#! /usr/bin/env python
import os
import argparse

def writable_dir(dir):
    if os.access(dir, os.W_OK) and os.path.isdir(dir):
        return os.path.abspath(dir)
    else:
        raise argparse.ArgumentTypeError(dir + " is not writable or does not exist.")

parser = argparse.ArgumentParser()
parser.add_argument("-d","--dir", type=writable_dir(), default='/tmp/',
    help="Directory to use. Default: /tmp")
opts = parser.parse_args()

Daraus ergibt sich folgendes:

$ python dir-test.py -h
usage: dir-test.py [-h] [-d DIR]

optional arguments:
  -h, --help         show this help message and exit
  -d DIR, --dir DIR  Directory to use. Default: /tmp

$ python dir-test.py -d /not/real
usage: dir-test.py [-h] [-d DIR]
dir-test.py: error: argument -d/--dir: /not/real is not writable or does not exist.

$ python dir-test.py -d ~

Ich ging zurück und fügte print opts.dir am Ende hinzu, und alles scheint wie gewünscht zu funktionieren.

1
796m9XfYTkmp

Wenn Sie die Berechtigung von einem anderen Benutzer prüfen müssen (Ja, ich weiß, dass dies der Frage widerspricht, aber für jemanden nützlich sein könnte), können Sie dies über das Modul pwd und die Modusbits des Verzeichnisses tun.

Disclaimer - 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 für ein Verzeichnis alle 3 Bits gesetzt sein müssen - Lesen, Schreiben und Ausführen.
Ok, R ist kein absolutes Muss, aber ohne sie können Sie die Einträge nicht im Verzeichnis auflisten (daher müssen Sie deren Namen kennen). Execute ist dagegen absolut notwendig - ohne dass der Benutzer die Inodes der Datei nicht lesen kann; also auch ohne W, ohne X-Dateien, kann nicht erstellt oder geändert werden. Genauere Erklärung unter diesem Link.

Schließlich stehen die Modi im Modul stat zur Verfügung, ihre Beschreibungen befinden sich in inode (7) man .

Beispielcode zum Ü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
0
Todor Minakov