在Python中更改文件权限

Changing file permission in Python

我正在尝试更改文件访问权限:

1
os.chmod(path, mode)

我想把它变为只读:

1
os.chmod(path, 0444)

有没有其他方法使文件只读?


1
os.chmod(path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)

统计

The following flags can also be used in the mode argument of
os.chmod():

stat.S_ISUID Set UID bit.

stat.S_ISGID Set-group-ID bit. This bit has several special uses. For
a directory it indicates that BSD semantics is to be used for that
directory: files created there inherit their group ID from the
directory, not from the effective group ID of the creating process,
and directories created there will also get the S_ISGID bit set. For a
file that does not have the group execution bit (S_IXGRP) set, the
set-group-ID bit indicates mandatory file/record locking (see also
S_ENFMT).

stat.S_ISVTX Sticky bit. When this bit is set on a directory it means
that a file in that directory can be renamed or deleted only by the
owner of the file, by the owner of the directory, or by a privileged
process.

stat.S_IRWXU Mask for file owner permissions.

stat.S_IRUSR Owner has read permission.

stat.S_IWUSR Owner has write permission.

stat.S_IXUSR Owner has execute permission.

stat.S_IRWXG Mask for group permissions.

stat.S_IRGRP Group has read permission.

stat.S_IWGRP Group has write permission.

stat.S_IXGRP Group has execute permission.

stat.S_IRWXO Mask for permissions for others (not in group).

stat.S_IROTH Others have read permission.

stat.S_IWOTH Others have write permission.

stat.S_IXOTH Others have execute permission.

stat.S_ENFMT System V file locking enforcement. This flag is shared
with S_ISGID: file/record locking is enforced on files that do not
have the group execution bit (S_IXGRP) set.

stat.S_IREAD Unix V7 synonym for S_IRUSR.

stat.S_IWRITE Unix V7 synonym for S_IWUSR.

stat.S_IEXEC Unix V7 synonym for S_IXUSR.


os.chmod(path, 0444)是用于在Python 2.x中更改文件权限的Python命令。对于组合的Python 2和Python 3解决方案,将0444更改为0o444

您总是可以使用Python来使用subprocess调用chmod命令。我认为这只适用于Linux。

1
2
3
import subprocess

subprocess.call(['chmod', '0444', 'path'])


所有当前的答案都破坏了非写入权限:它们使文件对每个人都可读但不可执行。当然,这是因为最初的问题要求444权限 - 但我们可以做得更好!

这是一个解决方案,使所有单独的"读取"和"执行"位保持不变。我写了详细的代码,以便于理解;如果你愿意,你可以把它变得更简洁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import stat

def remove_write_permissions(path):
   """Remove write permissions from this path, while keeping all other permissions intact.

    Params:
        path:  The path whose permissions to alter.
   """

    NO_USER_WRITING = ~stat.S_IWUSR
    NO_GROUP_WRITING = ~stat.S_IWGRP
    NO_OTHER_WRITING = ~stat.S_IWOTH
    NO_WRITING = NO_USER_WRITING & NO_GROUP_WRITING & NO_OTHER_WRITING

    current_permissions = stat.S_IMODE(os.lstat(path).st_mode)
    os.chmod(path, current_permissions & NO_WRITING)

为什么这样做?

正如John La Rooy所指出的,stat.S_IWUSR基本上意味着"用户写入权限的位掩码"。我们希望将相应的权限位设置为0.为此,我们需要完全相反的位掩码(即,在该位置具有0的位掩码,以及其他位置的1)。翻转所有位的~运算符给出了我们的确切结果。如果我们通过"按位和"运算符(&)将它应用于任何变量,它将把相应的位清零。

我们需要用"group"和"other"权限位重复这个逻辑。这里我们可以节省一些时间,只需将它们全部放在一起(形成NO_WRITING位常数)。

最后一步是获取当前文件的权限,并实际执行按位和操作。


只需在八进制中包含权限整数(适用于python 2和python3):

1
os.chmod(path, 0o444)


这里的FYI是将具有9个字符(例如'rwsr-x-wt')的权限字符串转换为可以与os.chmod()一起使用的掩码的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def perm2mask(p):

    assert len(p) == 9, 'Bad permission length'
    assert all(p[k] in 'rw-' for k in [0,1,3,4,6,7]), 'Bad permission format (read-write)'
    assert all(p[k] in 'xs-' for k in [2,5]), 'Bad permission format (execute)'
    assert p[8] in 'xt', 'Bad permission format (execute other)'

    m = 0

    if p[0] == 'r': m |= stat.S_IRUSR
    if p[1] == 'w': m |= stat.S_IWUSR
    if p[2] == 'x': m |= stat.S_IXUSR
    if p[2] == 's': m |= stat.S_IXUSR | stat.S_ISUID

    if p[3] == 'r': m |= stat.S_IRGRP
    if p[4] == 'w': m |= stat.S_IWGRP
    if p[5] == 'x': m |= stat.S_IXGRP
    if p[5] == 's': m |= stat.S_IXGRP | stat.S_ISGID

    if p[6] == 'r': m |= stat.S_IROTH
    if p[7] == 'w': m |= stat.S_IWOTH
    if p[8] == 'x': m |= stat.S_IXOTH
    if p[8] == 't': m |= stat.S_IXOTH | stat.S_ISVTX

    return m

注意,设置SUID / SGID / SVTX位将自动设置相应的执行位。如果没有这个,结果权限将无效(ST字符)。


无需记住旗帜。请记住,您始终可以:

subprocess.call(["chmod","a-w","file/path])

不便携但易于编写和记忆:

  • 你 - 用户
  • g - 组
  • o - 其他
  • a - 所有
  • +或 - (添加或删除权限)
  • r - 读
  • w - 写
  • x - 执行

有关其他选项和更详细的说明,请参阅man chmod