Pythonでスクリプトを実行しているユーザーがディレクトリに書き込み可能かどうかを判断する最良の方法は何でしょうか?これはおそらくosモジュールの使用を伴うため、 * nix環境。
クリストフが提案したのはよりPython的なソリューションですが、osモジュールにはアクセスをチェックするための os.access関数 があります:
os.access('/path/to/folder', os.W_OK)
#W_OKは書き込み用、R_OKは読み取り用などです。
これを提案するのは奇妙に思えるかもしれませんが、一般的なPythonイディオムは
許可よりも許しを求める方が簡単です
そのイディオムに続いて、人は言うかもしれない:
問題のディレクトリへの書き込みを試みて、許可がない場合はエラーをキャッチします。
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
更新:Windowsでコードを再度テストした後、そこでtempfileを使用すると実際に問題があることがわかります。 issue22107:tempfileモジュールがWindowsでアクセス拒否エラーを誤って解釈します 。書き込み不可のディレクトリの場合、コードは数秒間ハングし、最後にIOError: [Errno 17] No usable temporary file name found
。たぶん、これはuser2171842が観察していたことですか?残念ながら、この問題は現時点では解決されていないため、これを処理するには、エラーもキャッチする必要があります。
except (OSError, IOError) as e:
if e.errno == errno.EACCES or e.errno == errno.EEXIST: # 13, 17
もちろん、これらの場合、遅延は依然として存在します。
誰かの例を探してこのスレッドに出くわしました。 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")
これは、書き込みのためにファイルハンドルを開こうとし、指定されたファイルに書き込むことができない場合はエラーで終了します:これは読みやすく、ファイルパスまたはディレクトリで事前チェックを行うよりもはるかに良い方法です、競合状態を回避するため。事前チェックを実行してから実際にファイルへの書き込みを試みるまでの間にファイルが書き込み不可になる場合。
ファイルのパーマのみに関心がある場合、os.access(path, os.W_OK)
はあなたが求めることをするべきです。代わりに、ディレクトリに書き込むかcanかどうかを知りたい場合は、open()
書き込み用のテストファイル(存在しないはずです)事前に)、IOError
をキャッチして調べ、その後テストファイルをクリーンアップします。
より一般的には、 [〜#〜] toctou [〜#〜] 攻撃(スクリプトが昇格した特権で実行される場合のみ問題-suidまたはcgiなど)を避けるために、あなたは本当に信頼すべきではありませんこれらの事前テストは、特権を削除し、open()
を実行し、IOError
を期待します。
モードビットを確認します。
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)
)
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"
if os.access(path_to_folder, os.W_OK) is not True:
print("Folder not writable")
else :
print("Folder writable")
アクセスに関する詳細情報は、それを見つけることができます here
Argparseを介して引数を追加しているときに、この同じニーズに遭遇しました。ビルトインtype=FileType('w')
は、ディレクトリを探していたので機能しませんでした。私は自分の問題を解決するための独自のメソッドを書くことになりました。 argparseスニペットの結果は次のとおりです。
#! /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()
その結果、次のようになります。
$ 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 ~
戻ってprint opts.dirを最後に追加すると、すべてが期待どおりに機能しているように見えます。
他のユーザーの許可を確認する必要がある場合(はい、これは質問と矛盾することを理解していますが、誰かのために役立つかもしれません)、あなたはすることができますpwd
モジュール、およびディレクトリのモードビットを使用します。
免責事項-Windowsでは動作しません。POSIX権限モデルを使用しないためです(そしてpwd
モジュールはそこで利用できません) )、例えば-* nixシステム専用のソリューション。
ディレクトリには、読み取り、書き込み、実行の3ビットすべてを設定する必要があることに注意してください。
OK、Rは絶対的な必須ではありませんが、ディレクトリ内のエントリを一覧表示することはできません(名前を知っている必要があります)。一方、実行は絶対に必要です-ユーザーがファイルのiノードを読み取れない場合。したがって、XファイルなしでWを作成したり、変更したりすることはできません。 このリンクの詳細な説明
最後に、モードはstat
モジュールで利用可能です。それらは 説明は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