【问题标题】:Python module os.chmod(file, 664) does not change the permission to rw-rw-r-- but -w--wx----Python 模块 os.chmod(file, 664) 不会将权限更改为 rw-rw-r-- 但 -w--wx----
【发布时间】:2013-03-14 12:38:33
【问题描述】:

最近我在使用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 对获得正确结果如此重要?

【问题讨论】:

  • 八进制。八进制。八进制。
  • 我在 bugs.python.org/issue25377 上打开了一个 Python 文档问题,因为这应该从文档中明确。

标签: python file permissions chmod


【解决方案1】:

在different forum 上找到这个

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

你正在做的是传递664,八进制是1230

在你的情况下,你需要

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

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

【讨论】:

  • 谢谢,但我仍然很困惑,十进制的 484 意味着八进制的 744,这在您在论坛中提到的线程中是有道理的。但是,如果我给出十进制的 644,它会变成八进制的 1204。 1204 与八进制的 230 有何关系?
  • @AplusG:1没有被丢弃!那是sticky/setuid/setgid 位,1 表示sticky。使用ls -l,您可能会注意到权限现在在末尾包含T...
  • 更容易添加 0 并将其设为八进制 :)
  • 注意,对于 Python 3,您的前缀为 0o(零哦)。
  • 我在 python 2.7.10 中使用 0o
【解决方案2】:

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

$ chmod 755 somefile

用途:

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

如果您的 Python 版本早于 2.6:

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

【讨论】:

  • python3 格式也适用于 python 2.7.9。我没有检查过早期版本。
  • Python 3 语法可以追溯到 Python 2.6 docs.python.org/3/whatsnew/…
  • 为我工作 tks!
  • 应该是00755,只是为了清楚说明 suid/sgid/sticky 位的去向,以防后来一些开发人员通过并想要使用这个旧脚本,例如, sgid 与2755 但随后无法弄清楚为什么烫发完全搞砸了。 ;)
【解决方案3】:

使用权限符号 (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 stat 和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_IWRITE 和stat.S_IREAD 常量或相应的整数值)。所有其他位都被忽略。

chmod +x 演示在:How do you do a simple "chmod +x" from within python?

在 Ubuntu 16.04、Python 3.5.2 中测试。

【讨论】:

  • 这是处理问题的正确方法。
  • 我知道这是 python 的方式,但它几乎不可能更丑:)
【解决方案4】:

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

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

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

【讨论】:

    【解决方案5】:

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

    s = '660'
    os.chmod(file_path, int(s, base=8))
    

    【讨论】:

    • 优秀的现实用例
    【解决方案6】:

    在我看来,使用 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)
    

    【讨论】:

      【解决方案7】:

      @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))
      

      【讨论】:

        猜你喜欢
        • 2015-05-27
        • 2014-11-16
        • 1970-01-01
        • 2018-04-05
        • 2021-05-13
        • 1970-01-01
        • 2019-06-01
        • 1970-01-01
        • 2013-01-11
        相关资源
        最近更新 更多