Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set file permissions in Python3?

Python's own docs are quite terse about how to use functions like os.fchmod, os.chmod. I am confused by numbers like 777 and expressions like stat.S_IWRITE | stat.S_IEXEC.

And what is mode=0o777 I see in some functions in the os module?

Can you please explain what this is?

like image 848
oz123 Avatar asked Jun 28 '17 06:06

oz123


People also ask

How do I give Python permission to run a file?

Add execution permissions to the file (using chmod). Execute the script from command line , eg. by providing ./my_script.py when in the same directory.

How do I see file permissions in Python?

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.

How do I fix permission is denied in Python?

Permission denied simply means the system is not having permission to write the file to that folder. Give permissions to the folder using "sudo chmod 777 " from terminal and try to run it. It worked for me.


1 Answers

OK. Let's start from the beginning. If you know the linux chmod you are already are the right track to understand.

In Python 2, you could simply do for example in your Django project:

>>> os.chmod('manage.py', 0666)

and now you will see that the permissions have changed:

git diff
diff --git a/manage.py b/manage.py
old mode 100755
new mode 100644

The Python call you just saw is the direct equivalent of doing in bash:

chmod 0666 manage.py

In later Python versions you can use os functions with octal numbers:

>>> os.chmod('manage.py', 0o666)

This might look strange in the beginning. But it's just the new grammar introduced in pep3127. So instead of feeding Python with a 0 followed by an octal number, you feed Python with 0o followed by an octal numbers.

Finally, the stat module has numerical constants which you can combine with a bitwise OR operation on them. It's very verbose, but let's take a look at it.

>>> stat.S_IRUSR  # this means user read permissions
256

Which looks like an Integer. But actually is interpreted as a binary number by os.chmod, so you should read this like that:

>>> "{0:b}".format(stat.S_IRUSR)
'100000000'
>>>"{0:b}".format(stat.S_IWUSR)
'10000000'

Ok, that's confusing, but checkout out len on each result, the former is 1 bit longer

>>> len("{0:b}".format(stat.S_IWUSR))
8
>>> len("{0:b}".format(stat.S_IRUSR))
9

We can combine these stat constants to get a proper desired file mode:

>>> "{0:b}".format(stat.S_IRUSR|stat.S_IWUSR) # this is read and write for the user
'110000000'

In case you wonder | here is not a pipe as in base. This is the bitwise OR. The bit wise combination took both positive bits and gave us a result with a length of 9, with the first two bits set to 1. Which means the user can read an write the files.

Check this:

>>> "{0:b}".format(stat.S_IRUSR|stat.S_IWUSR|stat.S_IWGRP|stat.S_IRGRP)
'110110000'

This start looking like the usual chmod in bash:

$ chmod 0660 manage.py
$ ls -l manage.py 
-rw-rw---- 1 oznt oznt 805 Mar 31 16:38 manage.py

Bash represents the bits which are on not only as 1 or 0, but also as their meaning. So the 2nd bit from the left has is the read permission of the user, the 3rd is the write permission of the user. And the next group of bits are the group permission and so on.

Finally, you can combine the mode 666 in bash to this in Python:

os.chmod('manage.py', stat.S_IWGRP | stat.S_IRGRP | stat.S_IRUSR | stat.S_IWUSR | stat.S_IWOTH | stat.S_IROTH) 

And if that is too long, check again that you can do: os.chmod('manage.py', 0o666).

like image 75
oz123 Avatar answered Oct 15 '22 17:10

oz123