답변:
Christophe가 제안한 것이 더 Python적인 솔루션이지만 os 모듈에는 액세스를 확인 하는 os.access 함수 가 있습니다.
os.access('/path/to/folder', os.W_OK)
# W_OK는 쓰기, R_OK는 읽기 등입니다.
os.access()
사용하여 확인한다는 것입니다. 이로 인해 SUID / SGID 환경에서 이상이 발생할 수 있습니다. ( '하지만 스크립트는 setuid 루트를 실행하는데 왜 파일에 쓸 수 없습니까?')
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을 사용할 때 실제로 문제가 있음을 확인 했습니다. issue22107 : tempfile module misinterprets access denied error on 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의 첫 번째 결과, 축하합니다!
사람들은이 스레드에서 파이썬적인 방법에 대해 이야기하지만 간단한 코드 예제는 없습니까? 여기에 걸려 넘어지는 다른 사람을 위해 :
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 등)으로 실행되는 경우에만 문제) 이러한 사전 테스트를 신뢰해서는 안되지만 privs를 삭제하고을 수행 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 권한 모델을 사용하지 않기 때문에 Windows에서 작동하지 않습니다 (그리고 pwd
모듈은 여기에서 사용할 수 없습니다). 예 : * nix 시스템 전용 솔루션.
디렉토리에는 읽기, 쓰기 및 eXecute의 3 비트가 모두 설정되어 있어야합니다.
좋아, R은 절대 필수는 아니지만 디렉토리에 항목을 나열 할 수 없으므로 해당 이름을 알아야합니다. 반면에 실행은 절대적으로 필요합니다. 사용자는 파일의 inode를 읽을 수 없습니다. 따라서 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