Quel serait le meilleur moyen en Python de déterminer si un répertoire est accessible en écriture pour l'utilisateur exécutant le script? Comme cela impliquera probablement l'utilisation du module os, je dois mentionner que je l'utilise sous un environnement * nix.Déterminer si un répertoire est inscriptible
Répondre
Il peut sembler étrange de suggérer, mais un langage Python commun est
Il est plus facile de demander pardon que la permission
Après cet idiome, on pourrait dire:
Essayez d'écrire dans le répertoire en question, et interceptez l'erreur si vous n'en avez pas l'autorisation.
Vérifiez les bits de mode:
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)
)
Cette solution est uniquement Unix. –
Bien que Christophe a proposé une solution plus Pythonic, le module os n'ont the os.access function pour vérifier l'accès:
os.access('/path/to/folder', os.W_OK)
# W_OK est pour l'écriture, R_OK pour la lecture
Selon la situation, le "plus facile de demander pardon" n'est pas le meilleur moyen, même en Python. Il est parfois conseillé de "demander la permission" comme avec la méthode os.access() mentionnée, par exemple quand la probabilité d'avoir une erreur est élevée. – mjv
Il n'est pas suffisant de tester un répertoire uniquement pour le bit d'écriture si vous souhaitez écrire des fichiers dans le répertoire.Vous aurez également besoin de tester le bit d'exécution si vous voulez écrire dans le répertoire. os.access ('/ chemin/vers/dossier', os.W_OK | os.X_OK) Avec os.W_OK seul vous pouvez seulement supprimer le répertoire (et seulement si ce répertoire est vide) – fthinker
Un autre gotcha de 'os.access() 'est-ce qu'il vérifie en utilisant le * real * UID et le GID, pas les * effective *. Cela pourrait causer de l'étrangeté dans les environnements SUID/SGID. ('Mais le script s'exécute setuid root, pourquoi ne peut-il pas écrire dans le fichier?') – Alexios
Si vous vous souciez uniquement des perms de fichier, os.access(path, os.W_OK)
devrait faire ce que vous demandez. Si vous voulez savoir si vous pouvez pouvez écrire dans le répertoire, open()
un fichier de test pour l'écriture (il ne devrait pas exister au préalable), attraper et examiner tout IOError
, et nettoyer le fichier de test par la suite.
Plus généralement, pour éviter les attaques TOCTOU (seulement un problème si votre script s'exécute avec des privilèges élevés - suid ou cgi ou plus), vous ne devriez pas vraiment faire confiance à ces tests d'avance, mais laisser tomber les privs, le open()
, et attendez le IOError
.
Voici quelque chose que je créé sur la base de la réponse ChristopheD:
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"
Nous sommes tombés sur ce fil recherche d'exemples pour quelqu'un. Premier résultat sur Google, bravo!
Les gens parlent de la façon Pythonienne de le faire dans ce fil, mais pas de simples exemples de code? Ici, vous allez, pour quelqu'un d'autre qui trébuche dans:
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")
Cette tente d'ouvrir un descripteur de fichier pour l'écriture, et se termine avec une erreur si le fichier spécifié ne peut pas être écrit à: Ceci est beaucoup plus facile à lire et est une meilleure façon de le faire plutôt que de faire des préchecks sur le chemin du fichier ou le répertoire, car cela évite les conditions de course; cas où le fichier devient non-inscriptible entre le moment où vous exécutez le pré-contrôle et quand vous essayez réellement d'écrire dans le fichier.
Ceci s'applique à un fichier, pas à un répertoire qui est ce que l'OP a demandé. Vous pouvez avoir un fichier dans un répertoire et avoir le répertoire non inscriptible mais le fichier lui-même est, si le fichier existe déjà. Cela peut être important dans l'administration des systèmes où vous créez par exemple des fichiers journaux que vous voulez déjà exister mais que vous ne voulez pas que les personnes utilisent un répertoire de journaux pour l'espace temporaire. –
... et en fait je l'ai rejeté, ce que je pense maintenant était une erreur. Comme Rohaq l'a mentionné, il y a des problèmes de conditions de course. Il existe d'autres problèmes sur diverses plates-formes où vous pouvez tester le répertoire, et il semble accessible en écriture, mais ce n'est pas le cas. L'exécution de contrôles inscriptibles dans le répertoire multiplate-forme est plus difficile qu'il n'y paraît. Donc, tant que vous êtes au courant des problèmes, cela peut être une bonne technique. Je regardais cela d'un point de vue UNIX-y, ce qui est mon erreur. Quelqu'un édite cette réponse pour que je puisse retirer mon -1. –
Je l'ai édité, dans le cas où vous voulez supprimer le -1 :) Et oui, les vérifications de répertoires multiplateformes peuvent devenir plus compliquées, mais généralement vous cherchez à créer/écrire dans un fichier dans ce répertoire - Dans ce cas, l'exemple que j'ai donné devrait toujours s'appliquer. Si un problème lié à l'autorisation du répertoire survient, il doit toujours lancer une erreur IOError lors de la tentative d'ouverture du handle de fichier. – Rohaq
Ma solution à l'aide du module 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
Je pense que celui qui utilise tempfile est le nettoyeur car il ne laisse pas de résidus. – grasshopper
cette méthode ne fonctionne pas avec 'tempfile'. cela fonctionne seulement quand il n'y a pas de 'OSError' signifiant qu'il a l'autorisation d'écrire/supprimer. sinon, il ne renverra pas False car aucune erreur n'est renvoyée et le script ne continuera pas à s'exécuter ou à quitter. rien n'est retourné. c'est juste coincé à cette ligne. Cependant, la création d'un fichier non-temporaire comme la réponse de khattam fonctionne à la fois lorsque l'autorisation est autorisée ou refusée. Aidez-moi? –
if os.access(path_to_folder, os.W_OK) is not True:
print("Folder not writable")
else :
print("Folder writable")
plus d'informations sur l'accès peut être le trouver here
Ceci est essentiellement une copie de la réponse de Max Shawabkeh avec un peu d'emballage autour d'elle. Il fait une pâte de copie rapide mais une meilleure idée serait de l'avoir ajouté à l'article original de Max. –
Si vous devez vérifier l'autorisation de un autre utilisateur (oui, je réaliser ceci contredit la question, mais peut être utile pour quelqu'un), vous pouvez le faire via le module pwd
, et les bits de mode du répertoire.
Responsabilité - ne fonctionne pas sous Windows, car il n'utilise pas le modèle d'autorisations POSIX (et le module pwd
n'est pas là disponible), par exemple - solution uniquement pour les systèmes * nix.
Notez qu'un répertoire doit avoir tous les 3 bits définis - lecture, écriture et eXecute.
Ok, R n'est pas un must absolu, mais sans cela, vous ne pouvez pas lister les entrées dans le répertoire (vous devez donc connaître leurs noms). L'exécution d'un autre côté est absolument nécessaire - sans que l'utilisateur ne puisse lire les inodes du fichier; donc même avoir W, sans fichiers X ne peut pas être créé ou modifié. Enfin, les modes sont disponibles dans le module stat
, leur descriptions are in inode(7) man.
Exemple de code comment vérifier:
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. Comment vérifier si un fichier Windows est lisible/inscriptible?
- 2. Comment déterminer si un gif est animé?
- 3. C# .NET - comment déterminer si le répertoire est accessible en écriture, avec ou sans UAC?
- 4. smarty template compiler le répertoire non inscriptible
- 5. Déterminer si un répertoire peut être déplacé sur NTFS
- 6. Déterminer si un pathspec est un répertoire ou un fichier (ou quelque chose d'autre) via WMI?
- 7. Comment déterminer si un chemin de répertoire était SUBST?
- 8. Déterminer si un répertoire existe déjà en utilisant SVN ANT
- 9. Comment déterminer si un pthread est actif?
- 10. Déterminer si l'erreur $ .ajax est un délai
- 11. Déterminer si un type est statique
- 12. Comment déterminer si objet est un NSNumber
- 13. C#: Vérifier si un fichier n'est pas verrouillé et inscriptible
- 14. C# vérifie si un répertoire est caché?
- 15. Déterminer si l'utilisateur est connecté
- 16. déterminer si uiview est affiché
- 17. Comment tester ce test si un chemin est (ou non) inscriptible sans écrire rien dans ce
- 18. Comment vérifier si un fichier/dir est inscriptible dans les scripts batch
- 19. Comment déterminer si un groupe est un groupe de sécurité?
- 20. Déterminer si un type est un type anonyme
- 21. Ruby - déterminer si un nombre est un premier
- 22. C# - comment déterminer si un Type est un nombre
- 23. Regex pour déterminer si un fichier est un fichier rar
- 24. .NET: Comment déterminer si un objet est un objet COM?
- 25. Déterminer si un élément est un Widget jQueryUI
- 26. moyen efficace pour déterminer si un message est un spam?
- 27. Déterminer si un lien est cliqué sur un WebView - iPhone
- 28. Déterminer si un chemin est un chemin réseau VBA
- 29. façon mutualisées de vérifier si un fichier est un répertoire
- 30. Déterminer si la transaction SQLite3 est actif
+1 Python ou non, ce qui est vraiment le moyen le plus fiable pour tester l'accès. –
Cela prend également en charge d'autres erreurs qui peuvent se produire lors de l'écriture sur le disque - par exemple, il ne reste plus d'espace disque. C'est le pouvoir d'essayer .. vous n'avez pas besoin de se souvenir de tout ce qui peut aller mal ;-) –
Merci les gars. Décidé d'aller avec os.access comme la vitesse est un facteur important dans ce que je fais ici, même si je peux certainement comprendre les mérites dans "il est plus facile de demander pardon que pour la permission." ;) – illuminatedtiger