Checking File Permissions in Linux with Python
You're right that os.access, like the underlying access syscall, checks for a specific user (real rather than effective IDs, to help out with suid situations).
os.stat is the right way to get more general info about a file, including permissions per user, group, and others. The st_mode
attribute of the object that os.stat
returns has the permission bits for the file.
To help interpret those bits, you may want to use the stat module. Specifically, you'll want the bitmasks defined here, and you'll use the &
operator (bit-and) to use them to mask out the relevant bits in that st_mode
attribute -- for example, if you just need a True/False check on whether a certain file is group-readable, one approach is:
import os
import stat
def isgroupreadable(filepath):
st = os.stat(filepath)
return bool(st.st_mode & stat.S_IRGRP)
Take care: the os.stat
call can be somewhat costly, so make sure to extract all info you care about with a single call, rather than keep repeating calls for each bit of interest;-).
Check the permissions of a file in python
os.access
returns False
when the file does not exist, regardless of the mode parameter passed.
This isn't stated explicitly in the documentation for os.access
but it's not terribly shocking behavior; after all, if a file doesn't exist, you can't possibly access it. Checking the access(2) man page as suggested by the docs gives another clue, in that access
returns -1
in a wide variety of conditions. In any case, you can simply do as I did and check the return value in IDLE:
>>> import os
>>> os.access('does_not_exist.txt', os.R_OK)
False
In Python it's generally discouraged to go around checking types and such before trying to actually do useful things. This philosophy is often expressed with the initialism EAFP, which stands for Easier to Ask Forgiveness than Permission. If you refer to the docs again, you'll see this is particularly relevant in the present case:
Note: Using
access()
to check if a user is authorized to e.g. open a file before actually doing so usingopen()
creates a security
hole, because the user might exploit the short time interval between
checking and opening the file to manipulate it. It’s preferable to use
EAFP techniques. For example:if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
return "some default data"
is better written as:
try:
fp = open("myfile")
except IOError as e:
if e.errno == errno.EACCES:
return "some default data"
# Not a permission error.
raise
else:
with fp:
return fp.read()
If you have other reasons for checking permissions than second-guessing the user before calling open()
, you could look to How do I check whether a file exists using Python? for some suggestions. Remember that if you really need an exception to be raised, you can always raise
it yourself; no need to go hunting for one in the wild.
Since the IOError can be brought up a couple different ways (such as
permission denied, or non-existent directory), I am trying to get my
module to identify and publish the issue.
That's what the second approach above does. See:
>>> try:
... open('file_no_existy.gif')
... except IOError as e:
... pass
...
>>> e.args
(2, 'No such file or directory')
>>> try:
... open('unreadable.txt')
... except IOError as e:
... pass
...
>>> e.args
(13, 'Permission denied')
>>> e.args == (e.errno, e.strerror)
True
But you need to pick one approach or the other. If you're asking forgiveness, do the thing (open the file) in a try-except block and deal with the consequences appropriately. If you succeed, then you know you succeeded because there's no exception.
On the other hand, if you ask permission (aka LBYL, Look Before You Leap) in this that and the other way, you still don't know if you can successfully open the file until you actually do it. What if the file gets moved after you check its permissions? What if there's a problem you didn't think to check for?
If you still want to ask permission, don't use try-except; you're not doing the thing so you're not going to throw errors. Instead, use conditional statements with calls to os.access
as the condition.
Checking permission of a file using python
Yes, you can use Python's os.stat(path) or os.access(path) directly, e.g. to check it's executable
if os.access("/data/lims/LI", os.X_OK):
print "pass"
See Checking File Permissions in Linux with Python for more details.
Checking File Permissions in Linux with Python
You're right that os.access, like the underlying access syscall, checks for a specific user (real rather than effective IDs, to help out with suid situations).
os.stat is the right way to get more general info about a file, including permissions per user, group, and others. The st_mode
attribute of the object that os.stat
returns has the permission bits for the file.
To help interpret those bits, you may want to use the stat module. Specifically, you'll want the bitmasks defined here, and you'll use the &
operator (bit-and) to use them to mask out the relevant bits in that st_mode
attribute -- for example, if you just need a True/False check on whether a certain file is group-readable, one approach is:
import os
import stat
def isgroupreadable(filepath):
st = os.stat(filepath)
return bool(st.st_mode & stat.S_IRGRP)
Take care: the os.stat
call can be somewhat costly, so make sure to extract all info you care about with a single call, rather than keep repeating calls for each bit of interest;-).
check permissions of directories in python
Neither answer recurses, though it's not entirely clear that that's what the OP wants. Here's a recursive approach (untested, but you get the idea):
import os
import stat
import sys
MODE = "775"
def mode_matches(mode, file):
"""Return True if 'file' matches 'mode'.
'mode' should be an integer representing an octal mode (eg
int("755", 8) -> 493).
"""
# Extract the permissions bits from the file's (or
# directory's) stat info.
filemode = stat.S_IMODE(os.stat(file).st_mode)
return filemode == mode
try:
top = sys.argv[1]
except IndexError:
top = '.'
try:
mode = int(sys.argv[2], 8)
except IndexError:
mode = MODE
# Convert mode to octal.
mode = int(mode, 8)
for dirpath, dirnames, filenames in os.walk(top):
dirs = [os.path.join(dirpath, x) for x in dirnames]
for dirname in dirs:
if mode_matches(mode, dirname):
print dirname
Something similar is described in the stdlib documentation for
stat.
Check if file is deletable
Explanation
To check if file is deletable I have to check if file_path
has write permission.
os.access(file_path, os.W_OK)
This is not enough. Deleting a file requires also write and execute permissions on the directory containing the file. So I have to check if directory containing the file has write and execute premissions.
os.access(file_dirname, os.W_OK | os.X_OK)
This is still not enough. File can be locked by other process, so I have to check that I can access the file.
try:
file = open(file_path, 'w')
file.close()
except OSError:
print('File locked')
I can also check if file_path
is a file.
os.path.isfile(file_path)
Solution
def is_file_deletable(file_path):
''' return True if file is deletable, False otherwise '''
file_dirname = os.path.dirname(file_path) # get the directory name of file_path
if os.path.isfile(file_path): # if file_path exists and is a file
if os.access(file_path, os.W_OK): # if file_path has write permission
if os.access(file_dirname, os.W_OK | os.X_OK): # if directory containing file_path has write and execute permission
try: # if file_path can be opened for write
file = open(file_path, 'w') # Attention: This will delete all the content from the file
file.close()
return True # file_path is not locked
except OSError: # if file_path can't be opened for write
pass # file_path is locked
return False
Short version
def is_file_deletable(file_path):
file_dirname = os.path.dirname(file_path) # get the directory name of file_path
if os.access(file_dirname, os.W_OK | os.X_OK): # if folder containing file_path has write and execute permission
try: # if file_path can be opened for write
file = open(file_path, 'w') # Attention: This will delete all the content from the file
file.close()
return True # file_path is a file and has write permission and is not locked
except OSError: # if file_path can't be opened for write
pass # file_path is not a file, or don't has write permission or is locked
return False
Related Topics
How to Write Tests for the Argparse Portion of a Python Module
How to Match Any String from a List of Strings in Regular Expressions in Python
Convert Pandas Dataframe to a Nested Dict
Sphinx's Autodoc's Automodule Having Apparently No Effect
How to Make an Image with a Transparent Backround in Pygame
How to Show Explosion Image When Collision Happens
Why Do Many Examples Use 'Fig, Ax = Plt.Subplots()' in Matplotlib/Pyplot/Python
Reading/Writing Ms Word Files in Python
Why Can't Environmental Variables Set in Python Persist
Importing Flask.Ext Raises Modulenotfounderror
Identifying Objects, Why Does the Returned Value from Id(...) Change
Class Inheritance in Python 3.7 Dataclasses
Using Win32Com with Multithreading
How to Write String Literals in Python Without Having to Escape Them
Opencv Python Rotate Image by X Degrees Around Specific Point