128

最近我在使用 Python 模块 os,当我试图更改文件的权限时,我没有得到预期的结果。比如我打算把权限改成rw-rw-r--,

os.chmod("/tmp/test_file", 664)

所有权权限实际上是-w--wx--- (230)

--w--wx--- 1 ag ag 0 Mar 25 05:45 test_file

但是,如果我在代码中将 664 更改为 0664,结果正是我所需要的,例如

os.chmod("/tmp/test_file", 0664)

结果是:

-rw-rw-r-- 1 ag ag 0 Mar 25 05:55 test_file

任何人都可以帮助解释为什么前导 0 对获得正确结果如此重要吗?

4

7 回答 7

152

在另一个论坛上找到了这个

如果您想知道为什么前导零很重要,那是因为权限被设置为八进制整数,并且 Python 自动将具有前导零的任何整数视为八进制。所以 os.chmod("file", 484) (十进制)会给出相同的结果。

你正在做的是通过664八进制是1230

在你的情况下,你需要

os.chmod("/tmp/test_file", 436)

[更新] 注意,对于 Python 3,您的前缀为 0o(零哦)。例如,0o666

于 2013-03-25T05:01:14.547 回答
138

所以对于那些想要类似于以下语义的人:

$ chmod 755 somefile

利用:

$ python -c "import os; os.chmod('somefile', 0o755)"

如果您的 Python 版本早于 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
于 2013-07-21T20:50:14.463 回答
14

使用权限符号 ( stat.S_I*) 而不是原始八进制数

如果您使用更具语义命名的权限符号而不是原始幻数,则可以避免您的问题,例如664

#!/usr/bin/env python3

import os
import stat

os.chmod(
    'myfile',
    stat.S_IRUSR |
    stat.S_IWUSR |
    stat.S_IRGRP |
    stat.S_IWGRP |
    stat.S_IROTH
)

这记录在https://docs.python.org/3/library/os.html#os.chmod并且名称与POSIX C API相同,后者也存在于man 2 statand man 2 chmod

S_IRUSR  (00400)  read by owner
S_IWUSR  (00200)  write by owner
S_IXUSR  (00100)  execute/search by owner
S_IRGRP  (00040)  read by group
S_IWGRP  (00020)  write by group
S_IXGRP  (00010)  execute/search by group
S_IROTH  (00004)  read by others
S_IWOTH  (00002)  write by others
S_IXOTH  (00001)  execute/search by others

另一个优点是文档中提到的更大的可移植性:

注意:虽然 Windows 支持chmod(),但您只能使用它设置文件的只读标志(通过stat.S_IWRITEandstat.S_IREAD常量或相应的整数值)。所有其他位都被忽略。

chmod +x在以下位置进行了演示:您如何在 python 中执行简单的“chmod +x”?

在 Ubuntu 16.04、Python 3.5.2 中测试。

于 2019-04-09T10:45:46.770 回答
13

前导0表示这是八进制常量,而不是十进制常量。你需要一个八进制来改变文件模式。

权限是一个位掩码,例如,rwxrwx---111111000二进制的,并且很容易将位按 3 分组以转换为八进制,而不是计算十进制表示。

0644(八进制)是0.110.100.100二进制的(为了便于阅读,我添加了点),或者,你可以计算,420十进制。

于 2013-03-25T05:01:30.653 回答
7

如果您已将所需权限保存到字符串,请执行

s = '660'
os.chmod(file_path, int(s, base=8))
于 2020-02-04T07:54:36.690 回答
1

@mc.dev 的答案是最好的答案,我最终利用它来制作以下函数包装器以供重用。感谢您的分享。

def chmod_digit(file_path, perms):
    """
    Helper function to chmod like you would in unix without having to preface 0o or converting to octal yourself.
    Credits: https://stackoverflow.com/a/60052847/1621381
    """
    os.chmod(file_path, int(str(perms), base=8))
于 2021-04-22T02:10:37.517 回答
0

在我看来,使用 stat.* 位掩码确实是最便携和最明确的方式。但另一方面,我经常忘记如何最好地处理它。因此,这是一个屏蔽“组”和“其他”权限并保持“所有者”权限不变的示例。使用位掩码和减法是一种有用的模式。

import os
import stat
def chmodme(pn):
    """Removes 'group' and 'other' perms. Doesn't touch 'owner' perms."""
    mode = os.stat(pn).st_mode
    mode -= (mode & (stat.S_IRWXG | stat.S_IRWXO))
    os.chmod(pn, mode)
于 2020-04-08T14:26:53.163 回答