2010-01-21 87 views
75

Python中确定目录是否对执行脚本的用户可写的最佳方式是什么?由于这可能涉及使用os模块,我应该提到我正在* nix环境下运行它。确定目录是否可写

回答

55

它可能看起来很奇怪表明这一点,但一个共同的Python的成语是

它更容易请求原谅 比许可

继习语,人们可能会说:

尝试写入有问题的目录,并在没有权限的情况下捕获错误。

+4

+1 Python或没有,这是真的来测试访问的最可靠方法。 – 2010-01-21 22:32:32

+4

这还处理写入磁盘时可能发生的其他错误 - 例如,没有剩余磁盘空间。这是努力的力量..你不需要记住一切可能出错;-) – 2010-01-21 23:37:57

+4

谢谢你们。由于速度是我在这里做的事情的一个重要因素,所以决定和os.access一起去,尽管我当然可以理解“请求宽恕比容许更容易”的优点。 ;) – illuminatedtiger 2010-01-22 01:04:26

6

检查模式位:

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

此解决方案仅适用于Unix。 – 2013-09-26 15:00:07

127

虽然什么克里斯托夫认为是更Python的解决方案,操作系统模块确实有the os.access function检查访问:

os.access('/path/to/folder', os.W_OK)#W_OK是写作,R_OK阅读等

+4

根据情况,“容易请求原谅”并不是最好的方式,即使在Python中也是如此。有时候可以像上面提到的os.access()方法那样“询问权限”,例如当发生错误的概率很高时。 – mjv 2010-02-06 19:32:57

+34

如果要将文件写入目录,仅测试写入位是不够的。如果要写入目录,则还需要测试执行位。 os.access('/ path/to/folder',os.W_OK | os.X_OK)os.W_OK本身只能删除目录(只有当该目录为空时) – fthinker 2012-03-23 17:13:14

+3

os.access的另一个问题()'是否使用* real * UID和GID进行检查,而不是* *有效*进行检查。这可能会导致SUID/SGID环境中的怪异现象。 ('但脚本运行setuid root,为什么不能写入文件?') – Alexios 2016-05-13 08:37:28

9

如果你只关心文件权限,os.access(path, os.W_OK)应该做你所要求的。如果您想知道您是否可以可以写入目录open()用于写入的测试文件(它不应该事先存在),请捕获并检查任何IOError,然后清理测试文件。

更一般地说,为了避免TOCTOU攻击(如果脚本以提升的权限运行 - suid或cgi等),您不应该真正相信这些提前测试,但可以删除priv,do open(),并期望IOError

4

这里是我创建基于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" 
9

跨越这个线程搜索某人的例子绊倒了。在Google上的第一个结果,恭喜!

人们谈论Pythonic在这个线程中做的方式,但没有简单的代码示例?在这里,你走了,因为其他人谁在跌倒:

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

这种尝试打开用于写入的文件句柄,并以一个错误退出,如果指定的文件无法写入:这是更容易阅读,是一个更好的方式,而不是在文件路径或目录上进行预先检查,因为它避免了竞争条件;在运行预选检查时间以及实际尝试写入文件时,文件变得不可写入的情况。

+1

这适用于文件,而不是OP所要求的目录。您可以在目录中拥有一个文件,并且该目录不可写,但文件本身(如果该文件已存在)。这对于系统管理很重要,例如,您可以创建想要存在的日志文件,但不希望人们将日志目录用于临时空间。 – 2017-04-11 18:41:41

+0

......实际上我把它投下来了,我现在认为这是一个错误。正如Rohaq所提到的,有些问题与竞赛条件有关。在可以测试目录的各种平台上还有其他问题,它看起来是可写的,但实际上并不是这样。执行跨平台目录可写检查比看起来更难。所以只要你意识到这些问题,这可能是一个很好的技术。我从UNIX-Y的角度来看待它,这是我的错误。有人编辑这个答案,所以我可以删除我的-1。 – 2017-04-12 15:29:01

+0

我编辑它,以防你想删除-1 :) 是的,跨平台目录检查可能会变得更加复杂,但通常你正在寻找创建/写入该目录中的文件 - 在这种情况下,我给出的示例仍然适用。如果出现一些与目录权限相关的问题,它在尝试打开文件句柄时仍应该抛出IOError。 – Rohaq 2017-04-22 04:13:44

15

使用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 
+1

我认为使用tempfile的人更清洁,因为它肯定不会留下残留物。 – grasshopper 2014-12-31 00:59:06

+1

此方法不能使用'tempfile'。它只在没有'OSError'意味着它有写/删除权限时才起作用。否则它不会返回False,因为没有返回错误,并且脚本不会继续执行或退出。什么都没有返回。它只是停留在那条线上。然而,创建非临时文件(如khattam的答案)在允许或拒绝权限时都有效。帮帮我? – 2016-05-06 18:24:27

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

有关访问的详细信息,可以发现它here

+0

这基本上是一个Max Shawabkeh的答案和一个小包装的副本。使其成为快速复制粘贴,但更好的主意是将其添加到Max的原始帖子。 – 2017-08-20 18:21:52

0

如果您需要检查的另一个用户许可(是的,我意识到这个矛盾的问题,但可能会派上用场),你可以通过pwd模块和目录的模式位来完成。

免责声明 - 在Windows上不起作用,因为它不使用POSIX权限模型(并且pwd模块在那里不可用),例如, - 仅适用于* nix系统的解决方案。

请注意,目录必须设置所有3位 - 读,写和执行。
好的,R不是绝对必须的,但是无法列出目录中的条目(所以你必须知道它们的名字)。另一方面的执行是绝对需要的 - 没有用户无法读取文件的inode;所以即使有W,没有X文件也不能被创建或修改。 More detailed explanation at this link.

最后,这些模式在stat模块中可用,它们的descriptions are in inode(7) man

示例代码如何检查:

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 
相关问题