2010-01-21 94 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