回答:
クリストフが提案したのはよりPythonicなソリューションですが、osモジュールにはアクセスをチェックするos.access関数があります。
os.access('/path/to/folder', os.W_OK)
#W_OKは書き込み用、R_OKは読み取り用などです。
os.access()
は、有効なものではなく、実際の UIDとGID を使用してチェックすることです。これにより、SUID / SGID環境で奇妙な問題が発生する可能性があります。(「しかし、スクリプトはsetuid rootを実行しますが、なぜファイルに書き込めないのですか?」)
os.access(dirpath, os.W_OK | os.X_OK)
書き込みアクセス権がない場合でもTrueを返します。
これを提案するのは奇妙に思えるかもしれませんが、一般的なPythonイディオムは
許可よりも許しを求める方が簡単です
そのイディオムに従って、次のように言うかもしれません:
問題のディレクトリに書き込んでみて、権限がない場合はエラーをキャッチしてください。
except: pass
-この方法で、常に楽観的になり、自分を高く評価できます。/皮肉オフ。なぜ、たとえばファイルシステムのすべてのディレクトリに何かを書き込んで、書き込み可能な場所のリストを作成したいのですか?
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を使用すると実際に問題が発生することがわかりました。問題22107: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
もちろん、このような場合でも遅延は存在します。
誰かの例を探して、このスレッドを偶然見つけました。おめでとうございます。
このスレッドで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)
必要なことを行ってください。代わりに、ディレクトリに書き込むことができるかどうかを知りたい場合は、書き込み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")
アクセスの詳細については、こちらをご覧ください。
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
モジュールとディレクトリのモードビットを使用して確認できます。
免責事項 -POSIXアクセス許可モデルを使用していないため(そしてpwd
モジュールがそこで利用できないため)、Windowsでは機能しません。例-* nixシステム専用のソリューション。
ディレクトリには3ビットすべてが設定されている必要があることに注意してください-読み取り、書き込み、eXecute。
OK、Rは絶対に必要なものではありませんが、ディレクトリ内のエントリをリストすることはできません(そのため、それらの名前を知っている必要があります)。一方、実行は絶対に必要です-ユーザーがファイルのiノードを読み取ることができない場合。そのため、Wがあっても、Xファイルがなければ作成または変更できません。このリンクでより詳細な説明。
最後に、モードは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